PIPS
array_resizing_bottom_up.c
Go to the documentation of this file.
1 /*
2 
3  $Id: array_resizing_bottom_up.c 23373 2017-05-11 08:38:19Z ancourt $
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 
25 // do not compile unless required
26 #include "phases.h"
27 #ifdef BUILDER_ARRAY_RESIZING_BOTTOM_UP
28 
29 #ifdef HAVE_CONFIG_H
30 #include "pips_config.h"
31 #endif
32 /******************************************************************
33  *
34  * BOTTOM UP ARRAY RESIZING
35  *
36  *
37  *******************************************************************/
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #include "genC.h"
44 #include "linear.h"
45 
46 #include "ri.h"
47 #include "effects.h"
48 
49 #include "ri-util.h"
50 #include "prettyprint.h"
51 #include "effects-util.h"
52 
53 #include "pipsdbm.h"
54 #include "misc.h"
55 #include "properties.h"
56 
57 #include "semantics.h"
58 #include "effects-generic.h"
59 #include "effects-simple.h"
60 #include "effects-convex.h"
61 
62 #include "text-util.h" /* for words_to_string and get_prettyprint_language_tag */
63 /* get_prettyprint_language_tag can be replace by macro code_language in ri.h but less flexible */
64 
65 
67 static string current_mod ="";
68 static int opt = 0; /* 0 <= opt <= 7*/
69 static char *file_name = NULL;
70 static FILE * instrument_file; /*To store new array declarations*/
71 
72 #define PREFIX "$ARRAY_DECLARATION"
73 
74 static bool
76 {
77 
78  return storage_rom_p(entity_storage(e)) &&
82 }
83 
84 /*La valeur retournée est true si la variable v est un parameter
85  ou une variable common. Sinon, elle rend la valeur FALSE.*/
86 
87 static bool
88 variable_is_param_common_p(entity e)
89 {
90  if ( (parameter_p(e)) || (variable_in_common_p(e)) ) return (true);
91  else
92  return (false);
93 }
94 
95 /*Rendre true si la variable v n'est pas un parameter, ni une variable common
96  et v, v_phi ne sont pas identiques.
97  En vice-versa, retourner la valeur FALSE.*/
98 
99 static bool
100 variable_to_project_p(Variable v_phi, Variable v)
101 {
102  if (v!=v_phi) {
103  entity e = (entity) v;
104  if (variable_is_param_common_p(e) || storage_formal_p(entity_storage(e))) return false;
105  return true;
106  }
107  return false;
108 }
109 
110 static bool extract_constraint_on_var(Pvecteur p_var, Variable var, int val, Pvecteur *ptmp)
111 {
112  bool divisible=true;
113  Pvecteur p_tmp = VECTEUR_NUL,pv;
114  for (pv = p_var; !VECTEUR_NUL_P(pv) && divisible; pv=pv->succ) {
115  Variable v1=vecteur_var(pv);
116  if (v1 ==TCST)
117  divisible &= value_zero_p(value_mod(vect_coeff(TCST,p_var), val));
118  else if (v1!= var)
120  && value_zero_p(value_mod(pv->val, val)));
121  }
122  if (divisible) {
123  p_tmp = vect_dup(p_var);
124  vect_erase_var(&p_tmp,var);
125  for (pv = p_tmp; !VECTEUR_NUL_P(pv); pv=pv->succ) {
126  Variable v1=vecteur_var(pv);
127  vect_chg_coeff(&pv,v1, value_uminus(value_div(pv->val, val)));
128  }
129  *ptmp = p_tmp;
130  return(true);
131  }
132  else {
133  *ptmp = VECTEUR_NUL;
134  return (false);
135  }
136 }
137 
138 /* Traiter les égalités d'un systÚme de contraintes ps.
139  . Si la variable var apparaît dans ces égalités, *pe va contenir le vecteur
140  définissant var. Ex. :
141  Equation de la forme: k*var + q1*C1 + ... + p1*N1 + ... == 0
142  *pe contient le vecteur : (-q1/k)*C1 + ... + (-p1/k)*N1
143  . Sinon, pe est nulle. */
144 
145 static bool
146 extract_constraint_from_equalitites(Psysteme ps, Variable var, Pvecteur *pe)
147 {
148  Pcontrainte pc;
149  Value v_phi = VALUE_ZERO;
150  Pvecteur p_var = VECTEUR_NUL, ptmp= VECTEUR_NUL;
151  bool result=false;
152  if (!SC_UNDEFINED_P(ps) && !CONTRAINTE_UNDEFINED_P(ps->egalites)
153  && CONTRAINTE_NULLE_P(ps->egalites)) {
154  *pe = VECTEUR_NUL;
155  return(false);
156  }
157  for (pc = ps->egalites; pc != NULL; pc = pc->succ) {
158  /* équation de la forme: k*var + q1*C1 + ... + p1*N1 + ... == 0 */
159  p_var = contrainte_vecteur(pc);
160  v_phi = vect_coeff(var,p_var);
161  if (v_phi) {
162  result = extract_constraint_on_var(p_var,var,v_phi,&ptmp);
163  *pe=ptmp;
164  return(result);}
165  }
166  *pe = VECTEUR_NUL;
167  return(false);
168 }
169 
170 /*Simplifier le Pvecteur pv et extraire les parametres qui apparaissent dans pv.
171  Le Pvecteur résultat ne contient que les entiers et les variables commons.*/
172 static Pvecteur
173 vect_partial_eval(Pvecteur pv)
174 {
175  Pvecteur v = VECTEUR_NUL, v_tmp = VECTEUR_NUL, v_p_tmp = VECTEUR_NUL;
176  Value v_tcst = VALUE_ZERO;
177  while (!VECTEUR_NUL_P(pv)) {
178  Variable var = pv->var;
179  if (var == TCST)
180  v_tcst = value_plus(v_tcst, val_of(pv));
181  else if (parameter_p((entity) var)) {
183  pips_debug(8, "The variable %s is a parameter and its value is %lld\n",
184  entity_local_name((entity) var), val);
185  v_tcst = value_plus(v_tcst, value_direct_multiply(val, val_of(pv)));
186  }
187  else {
188  v_tmp = vect_new(pv->var, pv->val);
189  if (v == VECTEUR_NUL) {
190  v_p_tmp = v_tmp;
191  v = v_tmp;
192  }
193  else {
194  v_p_tmp->succ = v_tmp;
195  v_p_tmp = v_tmp;
196  }
197  }
198  pv = pv->succ;
199  }
200 
201  if (v_tcst != VALUE_ZERO) {
202  v_tmp = vect_new(TCST, v_tcst);
203  if (v == VECTEUR_NUL) {
204  v_p_tmp = v_tmp;
205  v = v_tmp;
206  }
207  else v_p_tmp->succ = v_tmp;
208  }
209  return (v);
210 }
211 
212 /* Faire la comparaison entre deux Pvecteurs basés sur le systÚme des préconditions ps_prec.
213  Cette fonction fait une combinaison sur 8 cas de la faisabilité d'un systÚme des contraintes
214  pour déterminer le Pvecteur supérieur et le Pvecteur inférieur.
215  Ces 8 cas proviennent des 3 systÚmes de contraintes :
216  i) sc_egal = { ps_prec , pv1 - pv2 = 0 }
217  ii) sc_inf = { ps_prec , pv1 - pv2 < 0 } = { ps_prec , pv1 - pv2 + 1 <= 0 }
218  iii) sc_sup = { ps_prec , pv2 - pv1 < 0 } = { ps_prec , pv2 - pv1 + 1 <= 0 }
219 
220  et le tableau de résultats est :
221 
222  sc_egal || .T. | .T. | .T. | .T. | .F. | .F. | .F. | .F.
223  --------------------------------------------------------------------------------------------
224  sc_inf || .T. | .T. | .F. | .F. | .T. | .T. | .F. | .F.
225  --------------------------------------------------------------------------------------------
226  sc_sup || .T. | .F. | .T. | .F. | .T. | .F. | .T. | .F.
227  ============================================================================================
228  Conclusion || * | pv1 <= pv2 | pv1 >= pv2 | pv1 = pv2 | * | pv1 < pv2 | pv1 > pv2 | *
229 
230  ( " * " correspondant au cas non-determiné )
231 
232  Dans le cas non-determiné, le Pvecteur retourné est VECTEUR_UNDEFINED et
233  on doit donc traiter le cas de VECTEUR_UNDEFINED avec les autres :
234 
235  a-/ VECTEUR_UNDEFINED et VECTEUR_UNDEFINED
236  b-/ VECTEUR_UNDEFINED et VECTEUR_ONE (1)
237  c-/ VECTEUR_UNDEFINED et un vecteur quelconque sauf VECTEUR_ONE */
238 static Pvecteur
239 sc_minmax_of_pvector(Psysteme ps_prec, Pvecteur pv1, Pvecteur pv2, bool is_min)
240 {
241  /* Automatic variables read in a CATCH block need to be declared volatile as
242  * specified by the documentation*/
243  Psysteme volatile ps_egal = SC_UNDEFINED;
244  Psysteme volatile ps_inf = SC_UNDEFINED;
245  Psysteme volatile ps_sup = SC_UNDEFINED;
246 
247  Psysteme pt= SC_UNDEFINED;
249  pc_inf = CONTRAINTE_UNDEFINED,
250  pc_sup = CONTRAINTE_UNDEFINED;
251  Pvecteur p1, p2, p_egal, p_inf, p_sup,pvt,pv_1;
252  bool egal = false, inf = false, sup = false;
253  Pvecteur p_one = vect_new(TCST, VALUE_ONE);
254 
255  if (VECTEUR_UNDEFINED_P(pv1) && VECTEUR_UNDEFINED_P(pv2)) {
256  vect_rm(p_one);
257  return VECTEUR_UNDEFINED;
258  }
259  else if (VECTEUR_UNDEFINED_P(pv1) && !VECTEUR_UNDEFINED_P(pv2)) {
260  if (!vect_equal(pv2, p_one)) {
261  vect_rm(p_one);
262  return (pv2);
263  }
264  else {
265  if (is_min)
266  return(p_one);
267  else
268  return VECTEUR_UNDEFINED;
269  }
270  }
271  else if ( VECTEUR_UNDEFINED_P(pv2) && !VECTEUR_UNDEFINED_P(pv1) ) {
272  if (!vect_equal(pv1, p_one)) {
273  vect_rm(p_one);
274  return (pv1);
275  }
276  else {
277  if (is_min)
278  return(p_one);
279  else
280  return VECTEUR_UNDEFINED;
281  }
282  }
283  p1 = vect_partial_eval(pv1);
284  p2 = vect_partial_eval(pv2);
285  p_egal = vect_substract(p1, p2);
286  if (VECTEUR_NUL_P(p_egal)) return(p1);
287 
288  /* Creation des trois systemes */
289  pvt=vect_dup(p_egal);
290  pc_egal = contrainte_make(pvt);
291  pt=sc_dup(ps_prec);
292  ps_egal = sc_equation_add(pt, pc_egal);
293  base_rm(ps_egal->base);
294  ps_egal->base = BASE_NULLE;
295  sc_creer_base(ps_egal);
296  ps_egal = sc_elim_redund(ps_egal);
297 
298  pv_1= vect_new(TCST, VALUE_ONE);
299  p_inf = vect_add(p_egal,pv_1);
300  vect_rm(pv_1);
301  pc_inf = contrainte_make(p_inf);
302  pt=sc_dup(ps_prec);
303  ps_inf = sc_inequality_add(pt, pc_inf);
304  base_rm(ps_inf->base);
305  ps_inf->base = BASE_NULLE;
306  sc_creer_base(ps_inf);
307  ps_inf = sc_elim_redund(ps_inf);
308 
309  pv_1= vect_new(TCST, VALUE_ONE);
310  p_sup = vect_substract(pv_1,p_egal);
311  vect_rm(pv_1);
312  pc_sup = contrainte_make(p_sup);
313  pt=sc_dup(ps_prec);
314  ps_sup = sc_inequality_add(pt, pc_sup);
315  base_rm(ps_sup->base);
316  ps_sup->base = BASE_NULLE;
317  sc_creer_base(ps_sup);
318  ps_sup = sc_elim_redund(ps_sup);
319 
321  pips_debug(8, "Overflow detected !\n");
322  sc_free(ps_egal);
323  sc_free(ps_inf);
324  sc_free(ps_sup);
325  return VECTEUR_UNDEFINED;
326  }
327  TRY {
328  egal = !SC_UNDEFINED_P(ps_egal) &&
330  inf = !SC_UNDEFINED_P(ps_inf) &&
332  sup = !SC_UNDEFINED_P(ps_sup) &&
334  sc_free(ps_egal);
335  sc_free(ps_inf);
336  sc_free(ps_sup);
338  if (is_min) { /* Recherche du minimum */
339  if ( (egal && inf && !sup) || (egal && !inf && !sup) || (!egal && inf && !sup) ) {
340  pips_debug(8, "p1 is minimum\n");
341  return (p1);
342  }
343  if ( (egal && !inf && sup) || (egal && !inf && !sup) || (!egal && !inf && sup) ) {
344  pips_debug(8, "p2 is minimum\n");
345  return (p2);
346  }
347  else {
348  pips_debug(8, "Non-determined\n");
349  return VECTEUR_UNDEFINED;
350  }
351  }
352  else { /* Recherche du maximum */
353  if ( (egal && inf && !sup) || (egal && !inf && !sup) || (!egal && inf && !sup) ) {
354  pips_debug(8, "p2 is maximum\n");
355  return (p2);
356  }
357  if ( (egal && !inf && sup) || (egal && !inf && !sup) || (!egal && !inf && sup) ) {
358  pips_debug(8, "p1 is maximum\n");
359  return (p1);
360  }
361  else {
362  pips_debug(8, "Non-determined\n");
363  return VECTEUR_UNDEFINED;
364  }
365  }
366  }
367 }
368 
369 /*Traiter les inégalités d'un systÚme de contraintes.
370  Si la variable var apparaît dans les inégalités, cette fonction va retourner la borne inférieure et la borne supérieure
371  de la variable var sous la forme de Pvecteur pmin et pmax. Sinon, la valeur retournée est false et les Pvecteurs sont nuls.
372  Dans cette fonction, il y a des appels à la fonction sc_min_max_of_pvector() pour comparer deux vecteurs. */
373 static bool
374 extract_constraint_from_inequalities(Psysteme ps, Variable var, Psysteme ps_prec, Pvecteur *pe, Pvecteur *pmin, Pvecteur *pmax)
375 {
376  Pcontrainte pc;
377  Value v_phi = VALUE_ZERO;
378  Pvecteur p_var = VECTEUR_NUL, ptmp = VECTEUR_NUL, p_max = VECTEUR_NUL, p_min = VECTEUR_NUL ;
379  p_max = vect_dup(*pe);
380  if (VECTEUR_NUL_P(*pe))
381  p_min = vect_new(TCST, VALUE_ONE);
382  else p_min = vect_dup(*pe);
383 
384  if (!SC_UNDEFINED_P(ps) && !CONTRAINTE_UNDEFINED_P(ps->inegalites)
385  && CONTRAINTE_NULLE_P(ps->inegalites)) {
386  *pmax = p_max;
387  *pmin = p_min;
388  return(false);
389  }
390  for (pc = ps->inegalites; pc != NULL; pc = pc->succ) {
391  p_var = contrainte_vecteur(pc);
392  v_phi = vect_coeff(var,p_var);
393  if (v_phi) {
394  (void)extract_constraint_on_var(p_var,var,v_phi,&ptmp);
395 
396  if (value_pos_p(v_phi))
397  p_max = sc_minmax_of_pvector(ps_prec, p_max, ptmp, false);
398  else if (value_neg_p(v_phi)) {
399  p_min = sc_minmax_of_pvector(ps_prec, p_min, ptmp, true);
400  }
401  }
402  }
403  *pmax = p_max;
404  *pmin = p_min;
405  return (true);
406 }
407 
408 /*Cette fonction a été écrite pour déterminer les valeurs minimum et maximum d'une variable dans
409  un systÚme de contraintes, elle est donc la fonction principale du programme.
410  . La valeur retournée est false si le systÚme de contraintes est infaisable ou les valeurs min, max sont
411  indéterminables. Et vice-versa, la valeur retournée est TRUE.
412  . Les pointeurs pmin et pmax contiennent les valeurs des bornes supérieure et inférieure
413  de la variable var dans le systÚme de contraintes ps. Ces valeurs sont des Pvecteurs.
414  Cette fonction contient les appels aux fonctions sc_egalites_of_variable() et sc_inegalites_of_variable()
415  pour traiter les égalités et les inégalités du systÚme ps. */
416 static bool
417 sc_min_max_of_variable(Psysteme ps, Variable var, Psysteme ps_prec, Pvecteur *min, Pvecteur *max)
418 {
419  Pbase b;
420  Pvecteur pe = VECTEUR_NUL;
421  Psysteme ps_e, ps_i;
422  bool ok2;
423  assert(var!=TCST);
424  *min = vect_new(TCST, VALUE_MIN);
425  *max = vect_new(TCST, VALUE_MAX);
426 
427  /* faire la projection sur toutes les variables sauf var, parametres formels et commons */
428  for (b = ps->base; !VECTEUR_NUL_P(b); b = b->succ) {
429  Variable v = var_of(b);
430  if (variable_to_project_p(var, v)) {
431  if (SC_EMPTY_P(ps = sc_projection_pure(ps, v)))
432  return false;
433  }
434  }
435  if (SC_EMPTY_P(ps = sc_normalize(ps)))
436  return false;
437 
438  if (SC_UNDEFINED_P(ps) || ( sc_nbre_inegalites(ps)==0 && sc_nbre_egalites(ps)==0))
439  return(false);
440 
441  ps_e = sc_dup(ps);
442  ps_i = sc_dup(ps);
443 
444  (void)extract_constraint_from_equalitites(ps_e, var, &pe);
445  ok2 = extract_constraint_from_inequalities(ps_i, var, ps_prec, &pe, min, max);
446  ifdebug(8) {
447  if (ok2)
448  pips_debug(8, "The upper bound has been found\n");
449  else
450  pips_debug(8, "The upper bound has not been found\n");
451  }
452 
453  vect_rm(pe);
454  sc_rm(ps_e);
455  sc_rm(ps_i);
456 
457  return (ok2);
458 }
459 
460 static void new_array_declaration_from_region(region reg, entity e, Psysteme pre)
461 {
463  list l_dims = variable_dimensions(v);
464  int length = gen_length(l_dims);
465  // Fortran is last dim/ C is first dim that can be changed without consequence on data structure
467  entity phi = entity_undefined;
468 
469  switch(get_prettyprint_language_tag()) {
471  case is_language_fortran:
472  dim = find_ith_dimension(l_dims,length);
473  phi = make_phi_entity(length);
474  break;
475  case is_language_c:
476  dim = find_ith_dimension(l_dims,1);
477  phi = make_phi_entity(1);
478  break;
479  default:
480  pips_internal_error("Language unknown !\n");
481  break;
482  }
483 
485  Pvecteur min,max;
486 
487  if (!region_undefined_p(reg))
488  {
489  /* there are cases when there is no region for one array */
490  Psysteme ps = sc_dup(region_system(reg));
491  if (sc_min_max_of_variable(ps, (Variable) phi, pre, &min, &max))
492  upper = Pvecteur_to_expression(max);
493  sc_rm(ps);
494  }
495 
496  if (expression_undefined_p(upper)) {
497  upper = make_unbounded_expression();
498  }
499 
500  if (!unbounded_expression_p(upper))
501  {
503  fprintf(instrument_file,"%s\t%s\t%s\t%s\t%d\t%s\t%s\n",PREFIX,file_name,
504  current_mod,entity_local_name(e),length,
506  expression_to_string(upper));
507  dimension_upper(dim) = upper;
508  }
509 }
510 
511 /**
512  * This function finds in the list of regions l_regions,
513  * the read and write store regions of e.
514  * If there are 2 regions, it returns the union region
515  */
516 static region find_union_store_regions(list l_regions,entity e)
517 {
518  region reg = region_undefined;
519  while (!ENDP(l_regions))
520  {
521  region re = REGION(CAR(l_regions));
522  if (store_effect_p(re)) {
525  if (same_entity_lname_p(array,e))
526  {
527  if (region_undefined_p(reg))
528  reg = region_dup(re);
529  else
530  reg = regions_must_convex_hull(reg,re);
531  }
532  }
533  l_regions = CDR(l_regions);
534  }
535  return reg;
536 }
537 
538 /* This phase do array resizing for all kind of arrays: formal or local,
539  unnormalized or not, depending on chosen option.
540  This pass can't work for C code. */
541 bool array_resizing_bottom_up(char* mod_name)
542 {
543  /* instrument_file is used to store new array declarations and will be used by
544  * a script to insert these declarations in the source code in xxx.database/Src/file_name.f
545  *
546  * file_name gives the file containing the current module in xxx.database/Src/ */
549 
550  list l_decl = code_declarations(entity_code(module)), l_regions = NIL;
551 
553  db_get_memory_resource(DBR_CODE, mod_name, true) );
555 
556  transformer mod_pre;
557  Psysteme pre;
558  string dir_name = db_get_current_workspace_directory();
559  string instrument_file_name = strdup(concatenate(dir_name, "/BU_instrument.out", NULL));
560  string user_file = db_get_memory_resource(DBR_USER_FILE,mod_name,true);
561  string base_name = pips_basename(user_file, NULL);
562  instrument_file = safe_fopen(instrument_file_name, "a");
564  "/",base_name,NULL));
565  current_mod = mod_name;
567  db_get_memory_resource(DBR_PRECONDITIONS,mod_name,true));
569  db_get_memory_resource(DBR_REGIONS, mod_name, true));
570  regions_init();
571  debug_on("ARRAY_RESIZING_BOTTOM_UP_DEBUG_LEVEL");
572  debug(1," Begin bottom up array resizing for %s\n", mod_name);
573  // In C this list is NIL or only contain formal parameter regions
574  // due to the local declaration
575  l_regions = load_rw_effects_list(stmt);
577  pre = predicate_system(transformer_relation(mod_pre));
578 
579  opt = get_int_property("ARRAY_RESIZING_BOTTOM_UP_OPTION");
580  /* opt in {0,1,2,3} => Do not compute new declarations for instrumented array (I_PIPS_MODULE_ARRAY)
581  * opt in {4,5,6,7} => Compute new declarations for instrumented array (I_PIPS_MODULE_ARRAY)
582  * => (opt mod 8)<= 3 or not
583  *
584  * opt in {0,1,4,5} => Compute new declarations for assumed-size and one arrays only
585  * opt in {2,3,6,7} => Compute new declarations for all kinds of arrays
586  * => (opt mod 4) <= 1 or not || get_bool_property("ARRAY_RESIZING_ASSUMED_SIZE_ONLY")
587  *
588  * opt in {0,2,4,6} => Do not compute new declarations for local array arguments
589  * opt in {1,3,5,7} => Compute new declarations for local array arguments also
590  * => (opt mod 2) = 0 or not || get_bool_property("ARRAY_RESIZING_ARGUMENT")
591  **/
592 
593  FOREACH(ENTITY, e, l_decl) {
594  if (opt%8 <= 3)
595  {
596  /* Do not compute new declarations for instrumented array (I_PIPS_MODULE_ARRAY)*/
597  if (opt%4 <= 1 /*|| get_bool_property("ARRAY_RESIZING_ASSUMED_SIZE_ONLY")*/)
598  {
599  /* Compute new declarations for assumed-size and one arrays only */
600  if (opt%2 == 1 /*|| get_bool_property("ARRAY_RESIZING_ARGUMENT")*/)
601  {
602  /* Compute new declarations for local array arguments also*/
603  if (unnormalized_array_p(e))
604  {
605  region reg = find_union_store_regions(l_regions,e);
606  new_array_declaration_from_region(reg,e,pre);
607  }
608  }
609  else
610  {
611  /* Do not compute new declarations for local array arguments */
613  {
614  region reg = find_union_store_regions(l_regions,e);
615  new_array_declaration_from_region(reg,e,pre);
616  }
617  }
618  }
619  else
620  {
621  /* Compute new declarations for all kinds of arrays
622  * To be modified, the whole C code: assumed-size bound if not success, ...
623  * How about multi-dimensional array ? replace all upper bounds ?
624  * => different script, ...*/
625 
626  user_log("This option has not been implemented yet\n");
627 
628  if (opt%2 == 1 /*|| get_bool_property("ARRAY_RESIZING_ARGUMENT")*/) {
629  /* Do not compute new declarations for local array arguments */
630  region reg = find_union_store_regions(l_regions,e);
631  new_array_declaration_from_region(reg,e,pre);
632  }
633  else {
634  if (!formal_parameter_p(e)) {
635  /* Compute new declarations for local array arguments also*/
636  region reg = find_union_store_regions(l_regions,e);
637  new_array_declaration_from_region(reg,e,pre);
638  }
639  }
640  }
641  }
642  else
643  {
644  /* Compute new declarations for instrumented array (I_PIPS_MODULE_ARRAY)
645  * Looking for arrays that contain I_PIPS in the last upper bound declaration
646  * Attention: this case excludes some other cases */
647  //if (pips_instrumented_array_p(e))
648  // {
649  // region reg = find_union_regions(l_regions,e);
650  // new_array_declaration_from_region(reg,e,pre);
651  // }
652  user_log("This option has not been implemented yet\n");
653  }
654  }
655  user_log("* Number of right array declarations replaced: %d *\n"
657 
658  debug(1,"End bottom up array resizing for %s\n", mod_name);
659  debug_off();
660  regions_end();
661 
666  safe_fclose(instrument_file,instrument_file_name);
667  free(dir_name), dir_name = NULL;
668  free(instrument_file_name), instrument_file_name = NULL;
669  free(file_name), file_name = NULL;
670  current_mod = "";
671  DB_PUT_MEMORY_RESOURCE(DBR_CODE, mod_name, stmt);
672 
673  return true;
674 }
675 
676 
677 /********************************************************
678  * linear function to find new min/max for C(/Fortran?) *
679  ********************************************************/
680 // Can replace the similar functions at the beginning of the files?
681 // Need to test it...
682 
683 // see extract_constraint_on_var
684 static bool extract_constraint_on_var_C(Pvecteur p_var, Variable var, int val, Pvecteur *ptmp)
685 {
686  bool divisible=true;
687  Pvecteur p_tmp = VECTEUR_NUL,pv;
688  for (pv = p_var; !VECTEUR_NUL_P(pv) && divisible; pv=pv->succ) {
689  Variable v1=vecteur_var(pv);
690  if (v1 ==TCST)
691  divisible &= value_zero_p(value_mod(vect_coeff(TCST,p_var), val));
692  else if (v1!= var)
694  && value_zero_p(value_mod(pv->val, val)));
695  }
696  if (divisible) {
697  p_tmp = vect_dup(p_var);
698  vect_erase_var(&p_tmp,var);
699  for (pv = p_tmp; !VECTEUR_NUL_P(pv); pv=pv->succ) {
700  Variable v1=vecteur_var(pv);
701  vect_chg_coeff(&pv,v1, value_uminus(value_div(pv->val, val)));
702  }
703  *ptmp = p_tmp;
704  return(true);
705  }
706  else {
707  *ptmp = VECTEUR_UNDEFINED;
708  return (false);
709  }
710 }
711 
712 // see extract_constraint_from_equalitites
713 static bool
714 extract_constraint_from_equalitites_C(Psysteme ps, Variable var, Pvecteur *pe)
715 {
716  Pcontrainte pc;
717  Value v_phi = VALUE_ZERO;
718  Pvecteur p_var = VECTEUR_NUL, ptmp= VECTEUR_NUL;
719  bool result=false;
720  if (!SC_UNDEFINED_P(ps) && !CONTRAINTE_UNDEFINED_P(ps->egalites)
721  && CONTRAINTE_NULLE_P(ps->egalites)) {
722  *pe = VECTEUR_UNDEFINED;
723  return(false);
724  }
725  for (pc = ps->egalites; pc != NULL; pc = pc->succ) {
726  /* équation de la forme: k*var + q1*C1 + ... + p1*N1 + ... == 0 */
727  p_var = contrainte_vecteur(pc);
728  v_phi = vect_coeff(var,p_var);
729  if (v_phi) {
730  result = extract_constraint_on_var_C(p_var,var,v_phi,&ptmp);
731  *pe=ptmp;
732  return(result);}
733  }
734  *pe = VECTEUR_UNDEFINED;
735  return(false);
736 }
737 
738 // see sc_minmax_of_pvector
739 // There is no test case in validation that really test this function...
740 static Pvecteur
741 sc_minmax_of_pvector_C(Psysteme ps_prec, Pvecteur pv1, Pvecteur pv2, bool is_min)
742 {
743  /* Automatic variables read in a CATCH block need to be declared volatile as
744  * specified by the documentation*/
745  Psysteme volatile ps_egal = SC_UNDEFINED;
746  Psysteme volatile ps_inf = SC_UNDEFINED;
747  Psysteme volatile ps_sup = SC_UNDEFINED;
748 
749  Psysteme pt= SC_UNDEFINED;
751  pc_inf = CONTRAINTE_UNDEFINED,
752  pc_sup = CONTRAINTE_UNDEFINED;
753  Pvecteur p1, p2, p_egal, p_inf, p_sup,pvt,pv_1;
754  bool egal = false, inf = false, sup = false;
755  // No more VECTEUR_UNDEFIED
756  // VECTEUR_NUL mean value 0 and no more undefined with the modification
757 // Pvecteur p_one = vect_new(TCST, VALUE_ONE);
758 //
759 // if (VECTEUR_UNDEFINED_P(pv1) && VECTEUR_UNDEFINED_P(pv2)) {
760 // vect_rm(p_one);
761 // return VECTEUR_UNDEFINED;
762 // }
763 // else if (VECTEUR_UNDEFINED_P(pv1) && !VECTEUR_UNDEFINED_P(pv2)) {
764 // if (!vect_equal(pv2, p_one)) {
765 // vect_rm(p_one);
766 // return (pv2);
767 // }
768 // else {
769 // if (is_min)
770 // return(p_one);
771 // else
772 // return VECTEUR_UNDEFINED;
773 // }
774 // }
775 // else if ( VECTEUR_UNDEFINED_P(pv2) && !VECTEUR_UNDEFINED_P(pv1) ) {
776 // if (!vect_equal(pv1, p_one)) {
777 // vect_rm(p_one);
778 // return (pv1);
779 // }
780 // else {
781 // if (is_min)
782 // return(p_one);
783 // else
784 // return VECTEUR_UNDEFINED;
785 // }
786 // }
787  p1 = vect_partial_eval(pv1);
788  p2 = vect_partial_eval(pv2);
789  p_egal = vect_substract(p1, p2);
790  if (VECTEUR_NUL_P(p_egal)) return(p1);
791 
792  /* Creation des trois systemes */
793  pvt=vect_dup(p_egal);
794  pc_egal = contrainte_make(pvt);
795  pt=sc_dup(ps_prec);
796  ps_egal = sc_equation_add(pt, pc_egal);
797  base_rm(ps_egal->base);
798  ps_egal->base = BASE_NULLE;
799  sc_creer_base(ps_egal);
800  ps_egal = sc_elim_redund(ps_egal);
801 
802  pv_1= vect_new(TCST, VALUE_ONE);
803  p_inf = vect_add(p_egal,pv_1);
804  vect_rm(pv_1);
805  pc_inf = contrainte_make(p_inf);
806  pt=sc_dup(ps_prec);
807  ps_inf = sc_inequality_add(pt, pc_inf);
808  base_rm(ps_inf->base);
809  ps_inf->base = BASE_NULLE;
810  sc_creer_base(ps_inf);
811  ps_inf = sc_elim_redund(ps_inf);
812 
813  pv_1= vect_new(TCST, VALUE_ONE);
814  p_sup = vect_substract(pv_1,p_egal);
815  vect_rm(pv_1);
816  pc_sup = contrainte_make(p_sup);
817  pt=sc_dup(ps_prec);
818  ps_sup = sc_inequality_add(pt, pc_sup);
819  base_rm(ps_sup->base);
820  ps_sup->base = BASE_NULLE;
821  sc_creer_base(ps_sup);
822  ps_sup = sc_elim_redund(ps_sup);
823 
825  pips_debug(2, "Overflow detected !\n");
826  sc_free(ps_egal);
827  sc_free(ps_inf);
828  sc_free(ps_sup);
829  if (is_min)
830  return vect_new(TCST, VALUE_MIN);
831  else
832  return vect_new(TCST, VALUE_MAX);
833  }
834  TRY {
835  egal = !SC_UNDEFINED_P(ps_egal) &&
837  inf = !SC_UNDEFINED_P(ps_inf) &&
839  sup = !SC_UNDEFINED_P(ps_sup) &&
841  sc_free(ps_egal);
842  sc_free(ps_inf);
843  sc_free(ps_sup);
845  if (is_min) { /* Recherche du minimum */
846  if ( (egal && inf && !sup) || (egal && !inf && !sup) || (!egal && inf && !sup) ) {
847  pips_debug(9, "p1 is minimum\n");
848  vect_rm(p2);
849  return (p1);
850  }
851  if ( (egal && !inf && sup) || (egal && !inf && !sup) || (!egal && !inf && sup) ) {
852  pips_debug(9, "p2 is minimum\n");
853  vect_rm(p1);
854  return (p2);
855  }
856  else {
857  pips_debug(9, "Non-determined\n");
858  vect_rm(p1);
859  vect_rm(p2);
860  return vect_new(TCST, VALUE_MIN);
861  }
862  }
863  else { /* Recherche du maximum */
864  if ( (egal && inf && !sup) || (egal && !inf && !sup) || (!egal && inf && !sup) ) {
865  pips_debug(9, "p2 is maximum\n");
866  vect_rm(p1);
867  return (p2);
868  }
869  if ( (egal && !inf && sup) || (egal && !inf && !sup) || (!egal && !inf && sup) ) {
870  pips_debug(9, "p1 is maximum\n");
871  vect_rm(p2);
872  return (p1);
873  }
874  else {
875  pips_debug(9, "Non-determined\n");
876  vect_rm(p1);
877  vect_rm(p2);
878  return vect_new(TCST, VALUE_MAX);
879  }
880  }
881  }
882  pips_internal_error("Never reach this point - dead code\n");
883 }
884 
885 // see extract_constraint_from_inequalities
886 static bool
887 extract_constraint_from_inequalities_C(Psysteme ps, Variable var, Psysteme ps_prec, bool egalite_p, Pvecteur *pe, Pvecteur *pmin, Pvecteur *pmax)
888 {
889  Pcontrainte pc;
890  Value v_phi = VALUE_ZERO;
891  Pvecteur p_var = VECTEUR_NUL, ptmp = VECTEUR_NUL, p_max = VECTEUR_NUL, p_min = VECTEUR_NUL ;
892  Pvecteur pv_min = vect_new(TCST, VALUE_MIN);
893  Pvecteur pv_max = vect_new(TCST, VALUE_MAX);
894  bool extract_ok;
895  if (egalite_p) {
896  p_min = vect_dup(*pe);
897  p_max = vect_dup(*pe);
898  }
899  else {
900  p_min = vect_new(TCST, VALUE_MAX);
901  p_max = vect_new(TCST, VALUE_MIN);
902  }
903  ifdebug(9) {
904  pips_debug(9, "begin p_min\n");
906  pips_debug(9, "begin p_max\n");
908  }
909 
910  if (!SC_UNDEFINED_P(ps) && !CONTRAINTE_UNDEFINED_P(ps->inegalites)
911  && CONTRAINTE_NULLE_P(ps->inegalites)) {
912  *pmax = p_max;
913  *pmin = p_min;
914  return(false);
915  }
916 
917  for (pc = ps->inegalites; pc != NULL; pc = pc->succ) {
918  ifdebug(9) {
919  pips_debug(9, "work on inequality\n");
921  }
922  p_var = contrainte_vecteur(pc);
923  v_phi = vect_coeff(var,p_var);
924  if (v_phi) {
925  extract_ok = extract_constraint_on_var_C(p_var,var,v_phi,&ptmp);
926 
927  if (extract_ok) {
928  if (value_pos_p(v_phi)) {
929  if (!vect_equal(p_max, pv_min) && !vect_equal(p_max, pv_max))
930  p_max = sc_minmax_of_pvector_C(ps_prec, p_max, ptmp, false);
931  else if (vect_equal(p_max, pv_min)) {
932  vect_rm(p_max);
933  p_max = ptmp;
934  }
935  }
936  else if (value_neg_p(v_phi)) {
937  if (!vect_equal(p_min, pv_min) && !vect_equal(p_min, pv_max))
938  p_min = sc_minmax_of_pvector_C(ps_prec, p_min, ptmp, true);
939  else if (vect_equal(p_min, pv_max)) {
940  vect_rm(p_min);
941  p_min = ptmp;
942  }
943  }
944  }
945  else {
946  if (value_pos_p(v_phi)) {
947  vect_rm(p_max);
948  p_max = vect_new(TCST, VALUE_MAX);
949  }
950  else if (value_neg_p(v_phi)) {
951  vect_rm(p_min);
952  p_min = vect_new(TCST, VALUE_MIN);
953  }
954  }
955 
956  ifdebug(9) {
957  pips_debug(9, "p_min\n");
959  pips_debug(9, "p_max\n");
961  }
962 
963  if (vect_equal(p_min, pv_min) && vect_equal(p_max, pv_max)) {
964  vect_rm(pv_min);
965  vect_rm(pv_max);
966  return false;
967  }
968  }
969  }
970  ifdebug(9) {
971  pips_debug(9, "end p_min\n");
973  pips_debug(9, "end p_max\n");
975  }
976  *pmax = p_max;
977  *pmin = p_min;
978  vect_rm(pv_min);
979  vect_rm(pv_max);
980  return (true);
981 }
982 
983 // see sc_min_max_of_variable
984 // with some modification the allow VECTEUR_NUL, that will really represent value 0 and not VECTEUR_UNDEFINED
985 // no more VECTEUR_UNDEFINED, use the return function to know if it's undefined
986 // min/max can return VALUE_MIN, VALUE_MAX, if failed find new bounds
987 // can replace sc_min_max_of_variable??? Need to test it...
988 static bool
989 sc_min_max_of_variable_C(Psysteme ps, Variable var, Psysteme ps_prec, Pvecteur *min, Pvecteur *max)
990 {
991  // Can this case really occur ?
992  //if (ENDP(ps) || list_undefined_p(ps))
993  // return false;
994 
995  Pbase b;
996  Pvecteur pe = VECTEUR_NUL;
997  Psysteme ps_e, ps_i;
998  bool ok_eg, ok2;
999  assert(var!=TCST);
1000  //*min = vect_new(TCST, VALUE_MIN);
1001  //*max = vect_new(TCST, VALUE_MAX);
1002 
1003  ifdebug(9) {
1004  pips_debug(9, "input system\n");
1006  }
1007 
1008  // Can this case really occur ?
1009  //if (ENDP(ps) || list_undefined_p(ps))
1010  // return false;
1011 
1012  /* faire la projection sur toutes les variables sauf var, parametres formels et commons */
1013  for (b = ps->base; !VECTEUR_NUL_P(b); b = b->succ) {
1014  Variable v = var_of(b);
1015  if (variable_to_project_p(var, v)) {
1016  if (SC_EMPTY_P(ps = sc_projection_pure(ps, v)))
1017  return false;
1018  }
1019  }
1020  if (SC_EMPTY_P(ps = sc_normalize(ps)))
1021  return false;
1022 
1023  if (SC_UNDEFINED_P(ps) || ( sc_nbre_inegalites(ps)==0 && sc_nbre_egalites(ps)==0))
1024  return(false);
1025 
1026  ps_e = sc_dup(ps);
1027  ps_i = sc_dup(ps);
1028 
1029  ifdebug(9) {
1030  pips_debug(9, "work on system\n");
1032  }
1033 
1034  ok_eg = extract_constraint_from_equalitites_C(ps_e, var, &pe);
1035  ok2 = extract_constraint_from_inequalities_C(ps_i, var, ps_prec, ok_eg, &pe, min, max);
1036  ifdebug(8) {
1037  if (ok2)
1038  pips_debug(8, "New bounds have been found\n");
1039  else
1040  pips_debug(8, "New bound have not been found\n");
1041  }
1042 
1043  vect_rm(pe);
1044  sc_rm(ps_e);
1045  sc_rm(ps_i);
1046 
1047  return (ok2);
1048 }
1049 
1050 /********************************************************
1051  * END linear function to find new min/max *
1052  ********************************************************/
1053 
1054 struct context_resizing
1055 {
1056  entity array; // array to resize
1057  list l_shift; // list of expression to shift
1058  // l_shift has the size of variable_dimensions(type_variable(entity_type(e))) list
1059  // if no shift needed for a dimension put expression_undefined
1060  // use copy_expression on the expression of the l_shift
1061  bool need_shift_p; // by default false
1062 };
1063 
1064 static struct context_resizing * make_context_resizing (entity e)
1065 {
1066  struct context_resizing * result = NULL;
1067  result = (struct context_resizing *) alloc(sizeof(struct context_resizing));
1068  if (result == NULL) {
1069  pips_internal_error("array_resizing, alloc failed.\n");
1070  }
1071  result->array = e;
1072  result->l_shift = NIL;
1073  result->need_shift_p = false;
1074  return result;
1075 }
1076 
1077 static void free_context_resizing(struct context_resizing * str)
1078 {
1079  free(str);
1080 }
1081 
1082 static list init_list_of_array_to_compute(list l_decl)
1083 {
1084  list result = NIL;
1085  struct context_resizing * to_add = NULL;
1086  bool compute_assumed_only = get_bool_property("ARRAY_RESIZING_ASSUMED_SIZE_ONLY");
1087  bool compute_argument = get_bool_property("ARRAY_RESIZING_ARGUMENT");
1088  pips_debug(5, "begin\n");
1089 
1090  FOREACH(ENTITY, e, l_decl) {
1091  if (array_type_p(entity_type(e))) {
1092  if (compute_argument) {
1093  /* Compute new declarations for array arguments */
1094  pips_user_warning("It can impact the caller function with the modification of the structure\n");
1095  //user_log("Not implemented yet.\n");
1096  if (compute_assumed_only) {
1097  /* Compute new declarations for assumed-size and one arrays only */
1098  // if (unnormalized_array_p(e)) {
1099  if (assumed_size_array_p(e)) {
1100  pips_debug(2, "0-add entity %s to analyze list\n", entity_name(e));
1101  to_add = make_context_resizing(e);
1102  result = gen_cons((const struct context_resizing *) to_add, result);
1103  }
1104  }
1105  else {
1106  /* Compute new declarations for all kinds of arrays */
1107  pips_debug(2, "1-add entity %s to analyze list\n", entity_name(e));
1108  to_add = make_context_resizing(e);
1109  result = gen_cons((const struct context_resizing *) to_add, result);
1110  }
1111  }
1112  else {
1113  /* Do not compute new declarations for array arguments */
1114  if (!formal_parameter_p(e)) {
1115  if (compute_assumed_only) {
1116  /* Compute new declarations for assumed-size and one arrays only */
1117  // if (unnormalized_array_p(e)) {
1118  if (assumed_size_array_p(e)) {
1119  pips_debug(2, "2-add entity %s to analyze list\n", entity_name(e));
1120  to_add = make_context_resizing(e);
1121  result = gen_cons((const struct context_resizing *) to_add, result);
1122  }
1123  }
1124  else {
1125  /* Compute new declarations for all kinds of arrays */
1126  pips_debug(2, "3-add entity %s to analyze list\n", entity_name(e));
1127  to_add = make_context_resizing(e);
1128  result = gen_cons((const struct context_resizing *) to_add, result);
1129  }
1130  }
1131  }
1132  to_add = NULL;
1133  }
1134  }
1135 
1136  pips_debug(5, "end\n");
1137  return result;
1138 }
1139 
1140 static void free_list_of_array_to_compute(list * l_ctx) {
1141  list l_temp = *l_ctx;
1142  for(struct context_resizing * elem; !ENDP(l_temp) && (elem= ((struct context_resizing *) (CAR(l_temp).p))); POP(l_temp)) {
1143  free_context_resizing(elem);
1144  }
1145 }
1146 
1147 static bool modify_array_declaration(statement st, list *ctx) {
1148  if (declaration_statement_p(st)) {
1149  ifdebug(5) {
1150  pips_debug(5, "begin\n");
1151  print_statement(st);
1152  }
1153  list l_decl = statement_declarations(st);
1156  Pvecteur pv_min = vect_new(TCST, VALUE_MIN);
1157  Pvecteur pv_max = vect_new(TCST, VALUE_MAX);
1158 
1159  bool c_array_notation = false;
1161 
1162  // foreach declaration,
1163  // if it is an array compute the new lower/upper bound
1164  // and remove the entity from the hash table if no shift access need to be done.
1165  FOREACH(ENTITY, e, l_decl) {
1166  // The first following if is for optimization, to not have to search into the context list
1167  if (array_type_p(entity_type(e))) {
1168  ifdebug(2) {
1169  pips_debug(2, "work on entity :\n");
1171  }
1172 
1173  // search entity array e in the context
1174  // if not present, it's not a array to analyze
1175  list l_temp = *ctx;
1176  for(struct context_resizing *compute_array; !ENDP(l_temp) && (compute_array= ((struct context_resizing *) (CAR(l_temp).p))); POP(l_temp)) {
1177  if (same_entity_p(e, compute_array->array)) {
1178  // we find the right element into the list
1179 
1180  // Verify that array e is present in useful_variables_regions resources
1183  // filter to only have store effects/regions
1184  // This filter can also be made in find_union_regions(), with function store_effect_p()
1185 // rwrg = effects_store_effects(rwrg);
1186  ifdebug(2) {
1187  pips_debug(2, "with rwrg :\n");
1189  }
1190  // note : rwrg has 0 (make clean declaration), 1 or 2 region for read and write
1191  //maybe direct convex hull if 2 region better than call find_union_regions
1192  region rg = find_union_store_regions((effects_effects(rwrg)), e);
1193  ifdebug(2) {
1194  pips_debug(2, "with region :\n");
1195  print_region(rg);
1196  }
1197 
1199  list l_dims = variable_dimensions(v);
1200 
1201  entity phi = entity_undefined;
1205  Pvecteur min, max;
1206  Psysteme ps = SC_UNDEFINED;
1207  int i=1; // i use for debug and warning message, AND create some PHI
1208 
1209  FOREACH(DIMENSION, dim, l_dims) {
1210  // search for new lower/upper bond
1211  phi = make_phi_entity(i);
1212  ps = sc_dup(region_system(rg));
1213  ifdebug(5) {
1214  pips_debug(5, "region system\n");
1216  pips_debug(5, "precondition system\n");
1218  }
1219  if (sc_min_max_of_variable_C(ps, (Variable) phi, pre, &min, &max)) {
1220  //if (vect_equal(max, pv_min) || vect_equal(min, pv_max))
1221  // pips_internal_error("This case never happens.\n");
1222 
1223  // TODO: improve lower/upper bound generation if min or/and max is symbolic
1224  // generate a ternary operator expression...
1225  if (!vect_equal(max, pv_max) && !vect_equal(max, pv_min))
1226  upper = Pvecteur_to_expression(max);
1227  else
1228  pips_user_warning("don't success to compute new upper bound for dimension index %d\n", i);
1229 
1230  if (!vect_equal(min, pv_min) && !vect_equal(min, pv_max)) {
1231  lower = Pvecteur_to_expression(min);
1232  if (!vecteur_nul_p(min)) {
1233  if (!vect_equal(max, pv_max) && !vect_equal(max, pv_min))
1235  else {
1236  normalized norm_upper = NORMALIZE_EXPRESSION(dimension_upper(dim));
1237  if (normalized_linear_p(norm_upper))
1239  else {
1240  pips_user_warning("Not linear index expression."
1241  "No implementation for complex expression yet."
1242  "Done nothing for dimension index %d\n", i);
1243  free_expression(lower);
1244  lower = expression_undefined;
1245  }
1246  }
1247  }
1248  }
1249  else
1250  pips_user_warning("don't success to compute new lower bound for dimension index %d\n", i);
1251  }
1252  sc_rm(ps);
1253  ps = SC_UNDEFINED;
1254  phi = entity_undefined;
1255 
1256  // modify the new lower bond for dimension dim
1257  if (!expression_undefined_p(lower)) {
1258  pips_debug(2, "new lower bound=%s\n",
1259  expression_to_string(lower));
1260  switch(language_tag(lang)) {
1261  case is_language_fortran95:
1262  case is_language_fortran:
1263  dimension_lower(dim) = lower;
1264  pips_user_error("Not implemented yet.\n");
1265  //if (expression_one_p(lower)) {
1266  //}
1267  break;
1268  case is_language_c:
1269  if (expression_null_p(lower)) {
1270  dimension_lower(dim) = lower;
1271  compute_array->l_shift = CONS(EXPRESSION, int_to_expression(0), compute_array->l_shift);
1272  }
1273  else if (!c_array_notation) {
1275  compute_array->l_shift = CONS(EXPRESSION, lower, compute_array->l_shift);
1276  compute_array->need_shift_p = true;
1277  // We have to shift all array accesses
1278  pips_debug(2, "%s access need to be shift with -%s for dimension %d\n",
1279  entity_name(e), expression_to_string(lower), i);
1280  }
1281  else {
1282  pips_user_error("C array notation not implemented yet.\n"
1283  "Warning :it's different from Fortran array notation.\n"
1284  "In C : a[start:nbr_element] \n");
1285  dimension_lower(dim) = lower;
1286  // compute_array->l_shift no need, since we don't make any shift
1287  //compute_array->l_shift = CONS(EXPRESSION, int_to_expression(0), compute_array->l_shift);
1288  }
1289  break;
1290  default:
1291  pips_internal_error("Language unknown !\n");
1292  break;
1293  }
1294  }
1295  else {
1296  compute_array->l_shift = CONS(EXPRESSION, int_to_expression(0), compute_array->l_shift);
1297  }
1298 
1299  // modify the new upper bond for dimension dim
1300  if (!expression_undefined_p(upper) || !expression_undefined_p(diff)) {
1301  ifdebug(2) {
1302  if (!expression_undefined_p(upper) && !expression_undefined_p(diff))
1303  pips_debug(2, "new upper bound: upper=%s, diff=%s\n",
1304  expression_to_string(upper),
1305  expression_to_string(diff));
1306  else if (!expression_undefined_p(upper))
1307  pips_debug(2, "new upper bound: upper=%s\n",
1308  expression_to_string(upper));
1309  else
1310  pips_debug(2, "new upper bound: diff=%s\n",
1311  expression_to_string(diff));
1312  }
1313  if (expression_undefined_p(diff))
1314  dimension_upper(dim) = upper;
1315  else {
1316  if (!(language_fortran_p(lang) || language_fortran95_p(lang) || c_array_notation))
1317  // language have not array notation
1318  dimension_upper(dim) = diff;
1319  else
1320  if (!expression_undefined_p(upper))
1321  dimension_upper(dim) = upper;
1322  }
1323  }
1324 
1325  i++;
1326  } // END FOREACH(DIMENSION, dim, l_dims)
1327 
1328  // reorder the index shift at the right place
1329  if (compute_array->need_shift_p) {
1330  compute_array->l_shift = gen_nreverse(compute_array->l_shift);
1331  ifdebug(3) {
1332  pips_debug(3, "shifted index factor :\n");
1333  FOREACH(EXPRESSION, es, compute_array->l_shift)
1334  print_expression(es);
1335  }
1336  }
1337  }
1338  else {
1339  //This case never happens
1340  pips_user_warning("unexpected case. entity %s not compute during useful_variables_regions?\n", entity_name(e));
1341  }
1342 
1343  ifdebug(2) {
1344  pips_debug(2, "entity with new bound :\n");
1346  }
1347  break;
1348  // We find the array to compute so no need to continue to iterate on the list
1349  }
1350  } // END for (ctx)
1351  }
1352  } // END FOREACH(ENTITY, e, l_decl)
1353  pips_debug(5, "end\n");
1354  vect_rm(pv_min);
1355  vect_rm(pv_max);
1356  }
1357  return true;
1358 }
1359 
1360 static bool shift_array_access(reference ref, list *ctx) {
1361  pips_debug(5, "begin\n");
1362 
1364  list l_indices = reference_indices(ref);
1365 
1366  // The first following if is for optimization, to not have to search into the context list
1367  if (array_type_p(entity_type(e))) {
1368  ifdebug(2) {
1369  pips_debug(2, "work on reference :\n");
1371  }
1372 
1373  // search entity array e in the context
1374  // if not present, it's not a array to analyze/shift
1375  list l_temp = *ctx;
1376  for(struct context_resizing *compute_array; !ENDP(l_temp) && (compute_array= ((struct context_resizing *) (CAR(l_temp).p))); POP(l_temp)) {
1377  if (same_entity_p(e, compute_array->array)) {
1378  // we find the right element into the list
1379  if (compute_array->need_shift_p) {
1380  list l_shift = compute_array->l_shift;
1381  // pips_assert("number of shift indices is equal to the number of indices.\n", gen_length(l_shift)==gen_length(l_indices));
1382 
1383  int current_index = 1;
1384  expression current_exp;
1385 
1386  FOREACH(EXPRESSION, current_shift, l_shift) {
1387  current_exp = EXPRESSION(CAR(l_indices));
1388  // Do we need to shift? expression_undefined mean no
1389  if (!expression_undefined_p(current_shift)) {
1390 
1391  normalized norm_exp = NORMALIZE_EXPRESSION(current_exp);
1392  normalized norm_shift = NORMALIZE_EXPRESSION(current_shift);
1393 
1394  if (normalized_linear_p(norm_exp) && normalized_linear_p(norm_shift)) {
1395  // compute new index expression shifted
1396  Pvecteur pv_exp = normalized_linear(norm_exp);
1397  Pvecteur pv_shift = normalized_linear(norm_shift);
1398  expression new_exp = Pvecteur_to_expression(vect_substract(pv_exp, pv_shift));
1399 
1400  // affect new index expression shifted
1401  free_syntax(expression_syntax(current_exp));
1402  expression_syntax(current_exp) = expression_syntax(new_exp);
1403  free_expression_normalized(current_exp);
1404  //expression_normalized(current_exp) = expression_normalized(new_exp);
1405  }
1406  else {
1407  // normally, never happen
1408  pips_internal_error("Not linear index expression.\n");
1409  }
1410  }
1411  l_indices = CDR(l_indices);
1412  current_index++;
1413  }
1414 
1415  ifdebug(5) {
1416  pips_debug(5, "new reference of array access shifted:\n");
1418  }
1419  }
1420  break;
1421  // We find the array to compute so no need to continue to iterate on the list
1422  }
1423  } // END for (ctx)
1424  }
1425 
1426  pips_debug(2, "end\n");
1427  return true;
1428 }
1429 
1430 
1431 bool array_resizing_full_bottom_up(char* mod_name) {
1432  entity module;
1434  bool good_result_p = true;
1435 
1436  debug_on("ARRAY_RESIZING_BOTTOM_UP_DEBUG_LEVEL");
1437  pips_debug(1, "begin\n");
1438 
1439  //-- configure environment --//
1442 
1444  db_get_memory_resource(DBR_CODE, mod_name, true) );
1446 
1447  pips_assert("Statement should be OK before...",
1449 
1450  //-- get dependencies --//
1452  db_get_memory_resource(DBR_PRECONDITIONS, mod_name, true));
1453 
1455  db_get_memory_resource(DBR_USEFUL_VARIABLES_REGIONS, mod_name, true));
1456 
1457  //-- Make the job -- //
1458  // 1. list the array variable to analyze
1460  list l_var = init_list_of_array_to_compute(l_decl);
1461 
1462 // // 2. Compute the new array size, and modify the declaration
1463 // gen_context_recurse(module_statement, &l_var,
1464 // statement_domain, gen_true, modify_array_declaration);
1465 // // 3. Shift the access on the array when necessary
1466 // gen_context_recurse(module_statement, &l_var,
1467 // reference_domain, gen_true, shift_array_access);
1468 
1469  // note: since declaration isn't an explicit statement that modify the code
1470  // we are not force to compute the new array bound and modify the entity (ie the declaration)
1471  // when we leave the statement.
1472  // The computation of the new bound and his memorization at the enter of the statement (in gen_recurse)
1473  // permits to fuse step 2 and 3.
1474  // Else the solution is to split modify_array_declaration in two function:
1475  // 1. to compute
1476  // solution to fuse step 2 and 3
1478  statement_domain, modify_array_declaration, gen_null,
1479  reference_domain, gen_true, shift_array_access,
1480  NULL);
1481 
1482  free_list_of_array_to_compute(&l_var);
1483 
1484  pips_assert("Statement should be OK after...",
1486 
1487  //-- Save modified code to database --//
1488  DB_PUT_MEMORY_RESOURCE(DBR_CODE, strdup(mod_name), module_statement);
1489 
1494 
1495  pips_debug(1, "end\n");
1496  debug_off();
1497 
1498  return (good_result_p);
1499 }
1500 
1501 #endif // BUILDER_ARRAY_RESIZING_BOTTOM_UP
1502 
int get_int_property(const string)
void user_log(const char *format,...)
Definition: message.c:234
bool statement_consistent_p(statement p)
Definition: ri.c:2195
void free_expression(expression p)
Definition: ri.c:853
void free_syntax(syntax p)
Definition: ri.c:2445
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static statement module_statement
Definition: alias_check.c:125
static entity current_mod
Definition: alias_check.c:120
#define CATCH(what)
@ overflow_error
#define UNCATCH(what)
#define TRY
#define value_pos_p(val)
#define VALUE_ZERO
#define int_to_value(i)
end LINEAR_VALUE_IS_INT
#define value_uminus(val)
unary operators on values
#define value_direct_multiply(v1, v2)
#define VALUE_MIN
#define value_zero_p(val)
int Value
#define VALUE_MAX
#define value_plus(v1, v2)
binary operators on values
#define VALUE_ONE
#define value_mod(v1, v2)
#define value_neg_p(val)
#define value_div(v1, v2)
#define PREFIX
This phase checks for out of bound error when passing arrays or array elements as arguments in proced...
char * alloc(int size)
ALLOC is an "iron-clad" version of malloc(3).
Definition: build.c:501
bool vecteur_nul_p(Pvecteur v)
Definition: constraint.c:56
#define CONTRAINTE_UNDEFINED_P(c)
#define CONTRAINTE_NULLE_P(c)
contrainte nulle (non contrainte 0 == 0 ou 0 <= 0)
#define contrainte_vecteur(c)
passage au champ vecteur d'une contrainte "a la Newgen"
#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
void inegalite_fprint(FILE *, Pcontrainte, char *(*)(Variable))
static bool parameter_p(entity e)
#define region_system(reg)
#define region_undefined
#define region_undefined_p(reg)
#define REGION
#define region
simulation of the type region
effect regions_must_convex_hull(region f1, region f2)
1- Union :
#define min(a, b)
#define max(a, b)
entity make_phi_entity(int)
void regions_end(void)
void regions_init(void)
effect region_dup(effect)
void reset_useful_variables_effects(void)
void set_rw_effects(statement_effects)
void set_useful_variables_effects(entity_effects)
effects load_useful_variables_effects(entity)
list load_rw_effects_list(statement)
void reset_rw_effects(void)
bool bound_useful_variables_effects_p(entity)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
bool store_effect_p(effect)
Definition: effects.c:1062
#define effects_effects(x)
Definition: effects.h:710
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
char * pips_basename(char *fullpath, char *suffix)
Definition: file.c:822
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
static int number_of_right_array_declarations
for words_to_string
static FILE * user_file
These functions implements the writing of objects.
Definition: genClib.c:1485
void free(void *)
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#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
size_t gen_length(const list l)
Definition: list.c:150
list gen_cons(const void *item, const list next)
Definition: list.c:888
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#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
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
language get_prettyprint_language()
please avoid using this function directly, use predicate instead (see below)
Definition: language.c:57
enum language_utype get_prettyprint_language_tag()
Definition: language.c:67
void vect_print(Pvecteur v, get_variable_name_t variable_name)
void vect_print(Pvecteur v, char * (*variable_name)()): impression d'un vecteur creux v sur stdout; l...
Definition: io.c:312
bool vect_equal(Pvecteur v1, Pvecteur v2)
bool vect_equal(Pvecteur v1, Pvecteur v2): test a egalite de deux vecteurs
Definition: reductions.c:278
string db_get_directory_name_for_module(const char *name)
returns the allocated and mkdir'ed directory for module name
Definition: lowlevel.c:150
#define debug_on(env)
Definition: misc-local.h:157
#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_user_warning
Definition: misc-local.h:146
#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 debug_off()
Definition: misc-local.h:160
#define pips_user_error
Definition: misc-local.h:147
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
#define assert(ex)
Definition: newgen_assert.h:41
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
@ is_min
Definition: optimize.c:710
void free_expression_normalized(expression e)
Definition: normalize.c:432
static char * module
Definition: pips.c:74
#define WORKSPACE_SRC_SPACE
Definition: pipsdbm-local.h:32
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
void print_entity_variable(entity e)
print_entity_variable(e)
Definition: entity.c:56
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
string expression_to_string(expression e)
Definition: expression.c:77
void print_reference(reference r)
Definition: expression.c:142
#define print_region(x)
Definition: print.c:343
#define print_effects(e)
Definition: print.c:334
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
bool same_entity_lname_p(entity, entity)
Definition: same_names.c:64
#define NORMALIZE_EXPRESSION(e)
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
bool assumed_size_array_p(entity e)
Definition: entity.c:807
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
code entity_code(entity e)
Definition: entity.c:1098
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool unnormalized_array_p(entity e)
Definition: entity.c:846
expression Pvecteur_to_expression(Pvecteur vect)
AP, sep 25th 95 : some usefull functions moved from static_controlize/utils.c.
Definition: expression.c:1825
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
expression make_unbounded_expression()
Definition: expression.c:4339
bool expression_null_p(expression exp)
returns true if the expression is equal to zero or NULL (even if there is a cast before such as in (v...
Definition: expression.c:2611
expression make_zero_expression(void)
Make a zero expression.
Definition: expression.c:1212
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
bool array_type_p(type)
Definition: type.c:2942
dimension find_ith_dimension(list, int)
This function returns the ith dimension of a list of dimensions.
Definition: type.c:5621
bool variable_in_common_p(entity)
true if v is in a common.
Definition: variable.c:1570
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define type_functional_p(x)
Definition: ri.h:2950
#define value_undefined_p(x)
Definition: ri.h:3017
#define storage_formal_p(x)
Definition: ri.h:2522
#define basic_int_p(x)
Definition: ri.h:614
#define normalized_linear_p(x)
Definition: ri.h:1779
#define reference_variable(x)
Definition: ri.h:2326
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define dimension_lower(x)
Definition: ri.h:980
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define code_declarations(x)
Definition: ri.h:784
#define value_symbolic(x)
Definition: ri.h:3070
#define language_fortran95_p(x)
Definition: ri.h:1597
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define value_symbolic_p(x)
Definition: ri.h:3068
#define entity_name(x)
Definition: ri.h:2790
#define transformer_relation(x)
Definition: ri.h:2873
#define dimension_upper(x)
Definition: ri.h:982
#define reference_indices(x)
Definition: ri.h:2328
#define dimension_undefined
Definition: ri.h:955
#define expression_undefined_p(x)
Definition: ri.h:1224
#define variable_dimensions(x)
Definition: ri.h:3122
#define statement_declarations(x)
Definition: ri.h:2460
#define storage_rom_p(x)
Definition: ri.h:2525
#define entity_type(x)
Definition: ri.h:2792
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define language_fortran_p(x)
Definition: ri.h:1591
#define language_tag(x)
Definition: ri.h:1590
#define predicate_system(x)
Definition: ri.h:2069
#define symbolic_expression(x)
Definition: ri.h:2597
@ is_language_fortran
Definition: ri.h:1566
@ is_language_fortran95
Definition: ri.h:1568
@ is_language_c
Definition: ri.h:1567
#define variable_basic(x)
Definition: ri.h:3120
#define entity_initial(x)
Definition: ri.h:2796
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_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
Psysteme sc_elim_redund(Psysteme ps)
Psysteme sc_elim_redund(Psysteme ps): elimination des contraintes lineaires redondantes dans le syste...
bool sc_rational_feasibility_ofl_ctrl(Psysteme sc, int ofl_ctrl, bool ofl_res)
Psysteme sc_inequality_add(Psysteme sc, Pcontrainte c)
Definition: sc_insert_eq.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_print(Psysteme ps, get_variable_name_t nom_var)
void sc_print()
Definition: sc_io.c:194
Psysteme sc_free(Psysteme in_ps)
Psysteme sc_free( in_ps ) AL 30/05/94 Free of in_ps.
Definition: sc_list.c:112
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
Psysteme sc_normalize(Psysteme ps)
Psysteme sc_normalize(Psysteme ps): normalisation d'un systeme d'equation et d'inequations lineaires ...
transformer load_statement_precondition(statement)
void reset_precondition_map(void)
void set_precondition_map(statement_mapping)
else
Definition: set.c:239
#define ifdebug(n)
Definition: sg.c:47
static entity array
struct Scontrainte * succ
Pcontrainte inegalites
Definition: sc-local.h:71
Pcontrainte egalites
Definition: sc-local.h:70
Pbase base
Definition: sc-local.h:75
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
Value val
Definition: vecteur-local.h:91
Variable var
Definition: vecteur-local.h:90
struct Svecteur * succ
Definition: vecteur-local.h:92
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54
bool array_resizing_bottom_up(char *)
array_resizing_bottom_up.c
bool array_resizing_full_bottom_up(char *)
static string file_name
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_var(v)
#define val_of(varval)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
#define VECTEUR_UNDEFINED
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62
#define VECTEUR_NUL_P(v)
#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 var_of(varval)
#define BASE_NULLE
MACROS SUR LES BASES.
#define OFL_CTRL
I do thing that overflows are managed in a very poor manner.
#define VECTEUR_UNDEFINED_P(v)
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
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
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
Pvecteur vect_add(Pvecteur v1, Pvecteur v2)
package vecteur - operations binaires
Definition: binaires.c:53
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2)
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2): allocation d'un vecteur v dont la valeur est la di...
Definition: binaires.c:75
void vect_erase_var(Pvecteur *ppv, Variable v)
void vect_erase_var(Pvecteur * ppv, Variable v): projection du vecteur *ppv selon la direction v (i....
Definition: unaires.c:106
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
void vect_chg_coeff(Pvecteur *ppv, Variable var, Value val)
void vect_chg_coeff(Pvecteur *ppv, Variable var, Value val): mise de la coordonnee var du vecteur *pp...
Definition: unaires.c:143