PIPS
utils.c
Go to the documentation of this file.
1 /*
2 
3  $Id: utils.c 23412 2017-08-09 15:07:09Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* package convex effects : Be'atrice Creusillet 5/97
28  *
29  * File: utils.c
30  * ~~~~~~~~~~~~~
31  *
32  * This File contains the interfaces with pipsmake which compute the various
33  * types of convex regions by using the generic functions.
34  *
35  *
36  * Actually this is the mere inclusion of the old utils.c of regions.
37  * Maybe it should be cleaned a little bit.
38  */
39 
40 /*
41  * package regions : Alexis Platonoff, 22 Aout 1990
42  * modified : Beatrice Creusillet
43  *
44  * This File contains useful functions for the computation of the regions.
45  *
46  * It can be sundered in seven groups of functions :
47  * _ manipulation of regions and lists of regions
48  * _ regions/list of regions conversion
49  * _ creation of regions
50  * _ phi entities
51  * _ properties
52  * _ variables and entities
53  * _ preconditions and transformers
54  */
55 
56 
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 
61 #include "genC.h"
62 #include "linear.h"
63 #include "ri.h"
64 #include "effects.h"
65 #include "database.h"
66 
67 #include "ri-util.h"
68 #include "prettyprint.h" // for debugging
69 #include "effects-util.h"
70 #include "constants.h"
71 #include "conversion.h"
72 #include "misc.h"
73 #include "text-util.h"
74 #include "text.h"
75 
76 #include "properties.h"
77 
78 #include "transformer.h"
79 #include "semantics.h"
80 
81 #include "effects-generic.h"
82 #include "effects-convex.h"
83 
84 #define IS_EG true
85 #define NOT_EG false
86 
87 #define PHI_FIRST true
88 #define NOT_PHI_FIRST false
89 
90 /******************************************************** BETA ENTITIES */
91 
92 #define BETA_MAX 5
93 static entity beta[BETA_MAX]; /* beta entities */
94 
95 /* entity make_beta_entity(int n)
96  * input : an integer n giving the range of the BETA entity.
97  * output : the entity BETA_n.
98  * modifies : beta[] (eventually).
99  * comment : finds or generates an entity representing a dummy variable.
100  *
101  * Once a BETA dummy entity, it is stored into a static array
102  * (beta[]); thus, each next time such an entity is needed,
103  * it is just picked up in beta[].
104  * If the dummy is not in beta[], it may be in the table
105  * where all entities are stored, because of previous computations.
106  * At last, if it is not found there, it is created.
107  */
109 {
110 
111  pips_assert("BETA range (n) must be between 1 and BETA_MAX\n",
112  1<=n && n<=BETA_MAX);
113 
114  /* beta indices are between 1 and BETA_MAX.
115  Array indices are between 0 to BETA_MAX - 1. */
116  if (beta[n-1] == entity_undefined)
117  {
118  entity v;
119  char beta_name[6];
120  char * s;
121 
122  sprintf(beta_name,"%s%d",BETA_PREFIX,n);
124  MODULE_SEP_STRING, beta_name, (char *) NULL));
125 
127  {
131  }
132 
133 
134 
135 
136  beta[n-1] = v;
137  }
138  return (beta[n-1]);
139 }
140 
141 
142 list beta_entities_list(int beta_min, int beta_max)
143 {
144  list l_beta = NIL;
145  int i;
146 
147  for(i=beta_min; i<=beta_max; i++)
148  l_beta = gen_nconc(l_beta, CONS(ENTITY, make_beta_entity(i), NIL));
149 
150  return(l_beta);
151 }
152 
153 /****************************************** INTIALISATION AND TERMINATION */
154 
155 static entity phi[NB_MAX_ARRAY_DIM]; /* phi entities */
156 static entity psi[NB_MAX_ARRAY_DIM]; /* psi entities */
157 static entity rho[NB_MAX_ARRAY_DIM]; /* rho entities */
158 
159 #ifndef bool_undefined
160 
161 #define bool_undefined ((bool) (-15))
162 #define bool_undefined_p(b) ((b)==bool_undefined)
163 #endif
164 
166 
167 void regions_init()
168 {
169  int i;
170  for(i=0; i<NB_MAX_ARRAY_DIM; i++)
171  {
172  phi[i] = entity_undefined;
173  psi[i] = entity_undefined;
174  rho[i] = entity_undefined;
175  }
176  for(i=0; i<BETA_MAX; i++)
177  {
178  beta[i] = entity_undefined;
179  }
182 }
183 
184 void regions_end()
185 {
188 
189 }
190 
191 /******************************* REGIONS AND LISTS OF REGIONS MANIPULATION */
192 
193 
195 {
196  region new_reg;
198 
199  pips_assert("region cell must be a reference\n",
201 
202  new_reg = copy_effect(reg);
203 
204  pips_assert("The copied region has the same persistent property as sthe input region",
205  cell_tag(effect_cell(new_reg))==cell_tag(effect_cell(new_reg)));
206 
207 
208  debug_region_consistency(new_reg);
209  pips_assert("No sharing of references",
210  region_any_reference(reg) != region_any_reference(new_reg));
211  return new_reg;
212 }
213 
214 
215 /* list regions_dup(list l_reg)
216  * input : a list of regions.
217  * output : a new list of regions, in which each region of the
218  * initial list is duplicated.
219  * modifies : nothing.
220  */
221 list regions_dup(list l_reg)
222 {
223  list l_reg_dup = NIL;
224 
225  FOREACH(EFFECT, eff, l_reg)
226  {
227  /* build last to first */
228  effect n_eff = region_dup(eff);
229  l_reg_dup = CONS(EFFECT, n_eff, l_reg_dup);
230  }
231 
232  /* and the order is reversed */
233  l_reg_dup = gen_nreverse(l_reg_dup);
234 
235  return l_reg_dup;
236 }
237 
238 
239 /* (void) regions_free(list l_reg)
240  * input : a list of regions
241  * output : nothing !
242  * modifies : frees the list and the regions
243  */
244 void regions_free(list l_reg)
245 {
246  MAP(EFFECT, reg,
247  {
248  region_free(reg);
249  }, l_reg);
250  gen_free_list(l_reg);
251 }
252 
253 /* (void) region_free(effect reg)
254  * input : a region
255  * output : nothing !
256  * modifies : frees region
257  * Unless function free_effect(), this function overrides the persistant attribute
258  * which may exist at the cell level. Macro free_region() does not exist anymore.
259  */
260 void region_free(region reg)
261 {
263 
264  pips_assert("region cell must be a reference\n",
266 
267  free_effect(reg);
268 }
269 
270 
271 /* void region_add_to_regions(region reg, list l_reg)
272  * input : a region and a list of regions.
273  * output : nothing.
274  * modifies : l_reg.
275  * comment : adds reg at the end of l_reg.
276  */
278 {
279  return gen_nconc(l_reg, CONS(REGION, reg, NIL));
280 }
281 
283 {
284  return gen_nconc(l_reg, CONS(REGION, reg, NIL));
285 }
286 
287 
288 /* list regions_add_context(list l_reg, transformer context)
289  * input : a list of regions and a precondition representing the current
290  * context.
291  * output : nothing.
292  * modifies : the input regions ; their predicates contain the initial
293  * constraints plus the constraints of the context, modulo
294  * the elimination of redundancies.
295  */
297 list l_reg;
299 {
300 
302  (l_reg,
304  2);
305  return(l_reg);
306 }
307 
308 /* adapted from transformer_normalize... which may have changed since
309  * then...
310  *
311  * FI: Normalization and redundancy elimination are often considered
312  * equivalent and used accordingly. Normalization is much more
313  * expensive: its purpose is not only to minimize the number of
314  * constraints, but also to rewrite them in a as canonical as possible
315  * way to simplify non-regression tests and to be as user-friendly as
316  * possible. Currently, region_sc_normaliza() is likely to be called instead of region_sc_redundancy_elimination(), if ever this function exists.
317  */
319 {
320  if (!sc_empty_p(sc_reg))
321  {
322  Pbase b = base_dup(sc_base(sc_reg));
323 
324  /* Select one tradeoff between speed and accuracy:
325  * enumerated by increasing speeds according to Beatrice
326  */
327 
328  switch(level)
329  {
330 
331  case 0:
332  /* Our best choice for accuracy, but damned slow on ocean */
333  sc_reg = sc_safe_elim_redund(sc_reg);
334  break;
335 
336  case 1:
337  /* Beatrice's best choice: does not deal with minmax2 (only)
338  * but still requires 74 minutes of real time
339  * (55 minutes of CPU time)
340  * for ocean preconditions, when applied to each precondition
341  * stored.
342  *
343  * Only 64 s for ocean, if preconditions are not normalized.
344  * But andne, callabsval, dead2, hind, negand, negand2, or,
345  * validation_dead_code are not validated any more. Redundancy
346  * could always be detected in a trivial way after propagating
347  * values from equations into inequalities.
348  */
349  // FI: not really effective
350  // sc_reg = sc_bounded_normalization(sc_reg);
351  // sc_reg = sc_bounded_normalization(sc_reg);
352  sc_nredund(&sc_reg);
353  break;
354 
355  case 2:
356  /* Francois' own: does most of the easy stuff.
357  * Fails on mimax2 and sum_prec, but it is somehow
358  * more user-friendly because trivial preconditions are
359  * not destroyed as redundant. It makes you feel safer.
360  *
361  * Result for full precondition normalization on ocean: 114 s
362  * for preconditions, 4 minutes between split ocean.f and
363  * OCEAN.prec
364  */
365  sc_reg = sc_strong_normalize(sc_reg);
366  break;
367 
368  case 5:
369  /* Same plus a good feasibility test
370  */
371  sc_reg = sc_strong_normalize3(sc_reg);
372  break;
373 
374  case 3:
375  /* Similar, but variable are actually substituted
376  * which is sometimes painful when a complex equations
377  * is used to replace a simple variable in a simple
378  * inequality.
379  */
380  sc_reg = sc_strong_normalize2(sc_reg);
381  break;
382  case 6:
383  /* Similar, but variables are substituted if they belong to
384  * a more or less simple equation, and simpler equations
385  * are processed first and a lexicographically minimal
386  * variable is chosen when equivalent variables are
387  * available.
388  */
389  sc_reg =
390  sc_strong_normalize4(sc_reg,
391  (char * (*)(Variable)) external_value_name);
392  break;
393 
394  case 7:
395  /* Same plus a good feasibility test, plus variable selection
396  * for elimination, plus equation selection for elimination
397  */
398  sc_reg =
399  sc_strong_normalize5(sc_reg,
400  (char * (*)(Variable)) external_value_name);
401  break;
402 
403  case 4:
404  /* Pretty lousy: equations are not even used to eliminate
405  * redundant inequalities!
406  */
407  sc_reg = sc_normalize(sc_reg);
408  break;
409 
410  default:
411  pips_internal_error("unknown level %d", level);
412  }
413 
414  if (SC_EMPTY_P(sc_reg))
415  sc_reg = sc_empty(b);
416  else
417  base_rm(b);
418 
419  sc_reg->dimension = vect_size(sc_reg->base);
420  }
421  return(sc_reg);
422 
423 }
424 
426 {
427  Psysteme sc;
428  Psysteme sc22 = sc_dup(sc2);
429 
430 
431  sc = sc1;
432  ifdebug(1)
433  {
434  pips_debug(1, "sc1 and sc2: \n");
435  sc_syst_debug(sc1);
436  sc_syst_debug(sc2);
437  pips_assert("sc1 must be consistent", sc_weak_consistent_p(sc1));
438  pips_assert("sc2 must be consistent", sc_weak_consistent_p(sc22));
439  }
440  sc22 = sc_safe_normalize(sc22);
441  ifdebug(1)
442  {
443  pips_debug(1, "sc22: \n");
444  sc_syst_debug(sc22);
445  }
446  sc = sc_safe_append(sc_safe_normalize(sc), sc22);
447  ifdebug(1)
448  {
450  }
451  if (level!=-1)
452  sc = region_sc_normalize(sc, level);
453 
454  ifdebug(1)
455  {
457  pips_debug(1, "returning sc: \n");
458  sc_syst_debug(sc);
459  }
460  sc_rm(sc22);
461 
462  return sc;
463 }
464 
465 
466 
467 /* void region_sc_append(region reg, Psysteme sc, bool nredund_p)
468  * input : a region and a Psysteme
469  * output : nothing.
470  * modifies : the initial region to which a copy of sc is appended.
471  * comment : add to the predicate of the region a copy of the system sc.
472  * redundancies are then eliminated if nredund_p is true.
473  * bug fixed 13/04/2000 CA/FC: sc MUST NOT be modified...
474  */
476 {
477  Psysteme sc_reg = region_system(reg);
478 
480 }
481 
482 /* void regions_sc_append(list l_reg, Psysteme sc, bool arrays_only,
483  * scalars_only, bool nredund_p)
484  * input : a list of regions, a Psysteme and two booleans.
485  * output : a list of regions;
486  * modifies : the regions contained in the list.
487  * comment : add to the predicate of each region the system sc. if arrays_only
488  * is true, scalar variables regions are not concerned. if
489  * scalars_only is true, array_variables are not concerned;
490  *
491  * usage : l_reg = regions_sc_append(l_reg, ...).
492  */
494  bool arrays_only, bool scalars_only,
495  int level)
496 {
497  list l_res = NIL;
498  pips_assert("not arrays_only and scalars_only", !(arrays_only && scalars_only));
499 
500  if (sc_empty_p(sc))
501  {
502  regions_free(l_reg);
503  }
504  else
505  {
506  FOREACH(EFFECT, reg, l_reg)
507  {
508  bool scalar_p = region_scalar_p(reg);
509 
510  if ((scalar_p && !arrays_only) || (!scalar_p && !scalars_only))
511  {
512  if(store_effect_p(reg)) {
514  if (!region_empty_p(reg))
515  l_res = region_add_to_regions(reg, l_res);
516  else
517  region_free(reg);
518  }
519  else {
520  l_res = region_add_to_regions(reg, l_res);
521  }
522  }
523  else
524  {
525  l_res = region_add_to_regions(reg, l_res);
526  }
527  }
528  gen_free_list(l_reg);
529  }
530  return(l_res);
531 }
532 
533 /* void array_regions_sc_append(list l_reg, Psysteme sc, bool nredund_p)
534  * input : a list of regions and the Psysteme to add.
535  * output : nothing.
536  * modifies : the regions contained in the list.
537  * comment : add to the predicate of each array region the system sc.
538  */
540 {
541  l_reg = regions_sc_append_and_normalize(l_reg, sc, true, false, level);
542  return(l_reg);
543 }
544 
545 
546 /* void region_sc_append(region reg, Psysteme sc, bool nredund_p)
547  * input : a region and a Psysteme
548  * output : nothing.
549  * modifies : the initial region to which a copy of sc is appended.
550  * comment : add to the predicate of the region a copy of the system sc.
551  * redundancies are then eliminated if nredund_p is true.
552  */
553 void region_sc_append(region reg, Psysteme sc, bool nredund_p)
554 {
555  int level = nredund_p? 1: -1;
557 }
558 
559 /* void regions_sc_append(list l_reg, Psysteme sc, bool arrays_only,
560  * scalars_only, bool nredund_p)
561  * input : a list of regions, a Psysteme and two booleans.
562  * output : a list of regions;
563  * modifies : the regions contained in the list.
564  * comment : add to the predicate of each region the system sc. if arrays_only
565  * is true, scalar variables regions are not concerned. if
566  * scalars_only is true, array_variables are not concerned;
567  *
568  * usage : l_reg = regions_sc_append(l_reg, ...).
569  */
571  bool arrays_only, bool scalars_only,
572  bool nredund_p)
573 {
574  int level = nredund_p? 1: -1;
575  return(regions_sc_append_and_normalize(l_reg, sc,
576  arrays_only, scalars_only,
577  level));
578 }
579 
580 
581 /* void all_regions_sc_append(list l_reg, Psysteme sc, bool nredund_p)
582  * input : a list of regions and the Psysteme to add.
583  * output : nothing.
584  * modifies : the regions contained in the list.
585  * comment : add to the predicate of each region the system sc.
586  */
587 list all_regions_sc_append(list l_reg, Psysteme sc, bool nredund_p)
588 {
589  l_reg = regions_sc_append(l_reg, sc, false, false, nredund_p);
590  return(l_reg);
591 }
592 
593 /* void scalar_regions_sc_append(list l_reg, Psysteme sc, bool nredund_p)
594  * input : a list of regions and the Psysteme to add.
595  * output : nothing.
596  * modifies : the regions contained in the list.
597  * comment : add to the predicate of each region the system sc.
598  */
599 list scalar_regions_sc_append(list l_reg, Psysteme sc, bool nredund_p)
600 {
601  l_reg = regions_sc_append(l_reg, sc, false, true, nredund_p);
602  return(l_reg);
603 }
604 
605 /* void array_regions_sc_append(list l_reg, Psysteme sc, bool nredund_p)
606  * input : a list of regions and the Psysteme to add.
607  * output : nothing.
608  * modifies : the regions contained in the list.
609  * comment : add to the predicate of each array region the system sc.
610  */
611 list array_regions_sc_append(list l_reg, Psysteme sc, bool nredund_p)
612 {
613  l_reg = regions_sc_append(l_reg, sc, true, false, nredund_p);
614  return(l_reg);
615 }
616 
617 
618 
619 
620 
621 
622 
623 /* list regions_remove_variable_regions(list l_reg, l_var)
624  * input : a list of reigons and a list of variables
625  * output : a list of regions
626  * modifies : nothing.
627  * comment : the returned list of regions is the same as the input
628  * list, except that the regions corresponding to the variables
629  * in l_var are removed.
630  */
632 {
633  list l_res = NIL;
634 
635  MAP(REGION, reg,
636  {
637  if (gen_find_eq(region_entity(reg),l_var) == entity_undefined)
638  l_res = region_add_to_regions(reg,l_res);
639  else
640  pips_debug(7, "Region on variable %s removed\n",
642  }, l_reg);
643  return(l_res);
644 }
645 
646 
647 /* void array_regions_variable_rename(list l_reg, entity old_entity, new_entity)
648  * input : a list of regions, and two variables
649  * output : nothing.
650  * modifies : the list of regions
651  * comment : in the array regions of l_reg, the variable old_entity
652  * that appears in the predicates is replaced with new_entity.
653  *
654  * Note: the subscripts of the region reference are not updated
655  *
656  * See also region_value_substitute(), all_regions_variable_rename()
657  */
658 void array_regions_variable_rename(list l_reg, entity old_entity, entity new_entity)
659 {
660  FOREACH(EFFECT, reg, l_reg) {
661  if (!region_scalar_p(reg)) {
662  Psysteme sc_reg = region_system(reg);
663 
664  if (!sc_empty_p(sc_reg) && !sc_rn_p(sc_reg))
665  sc_reg = sc_variable_rename(sc_reg, (Variable) old_entity,
666  (Variable) new_entity);
667  }
668  }
669 }
670 
671 /* void array_regions_variable_rename(list l_reg, entity old_entity, new_entity)
672  * input : a list of regions, and two variables
673  * output : nothing.
674  * modifies : the list of regions
675  * comment : in the array regions of l_reg, the variable old_entity
676  * that appears in the predicates is replaced with new_entity.
677  *
678  * Note: the subscripts of the region reference are not updated
679  */
681  entity old_entity,
682  entity new_entity)
683 {
684  FOREACH(EFFECT, reg, l_reg) {
685  if(store_effect_p(reg)) {
686  Psysteme sc_reg = region_system(reg);
687 
688  if (!sc_empty_p(sc_reg) && !sc_rn_p(sc_reg)) {
689  Pbase b = sc_base(sc_reg);
690  ifdebug(8){
691  pips_debug(8, "current system: \n");
692  sc_syst_debug(sc_reg);
693  }
694 
695  /* FI: I do not know if I'm fixing a bug or if I'm correcting a symptom */
696  /* This is done to ocmpute the OUT regions of the routine
697  COMPUTE_PD3 in the NAS beanchmark md. (Request Alain Muller) */
698  if(base_contains_variable_p(b, (Variable) new_entity)) {
699  Pbase nb = sc_to_minimal_basis(sc_reg);
700  if(base_contains_variable_p(nb, (Variable) new_entity)) {
701  /* We are in trouble because we cannot perform a simple renaming */
702  /* The caller may reuse values already used in the
703  system. This is the case for muller01.f because the
704  precondition and the region rightly used I#old. Rightly,
705  but uselessly in that case. */
706  /* new_entity must/can be projected first although this is
707  dangerous when dealing with MUST/MAY regions (no other
708  idea, but use of temporary values t# instead of i#old in
709  caller, ).. */
711  sc_reg = region_system(reg);
712  pips_user_warning("Unexpected variable renaming in a region\n");
713  }
714  else {
715  base_rm(b);
716  sc_base(sc_reg) = nb;
717  sc_dimension(sc_reg) = base_dimension(nb);
718  }
719  }
720 
721  sc_reg = sc_variable_rename(sc_reg, (Variable) old_entity,
722  (Variable) new_entity);
723  }
724  }
725  else {
726  /* FI: for the time being, other kinds of regions do not have
727  descriptors */
728  ;
729  }
730  }
731 }
732 
733 /* void region_value_substitute(region reg, entity e1, entity e2)
734  * input : an effect, an old entity e1 to rename into a new entity e2.
735  * output : nothing
736  * modifies : the system of reg.
737  * comment : adapted from transformer_value_substitute.
738  *
739  * if e2 does not appear in t initially:
740  * replaces occurences of value e1 by value e2 in transformer t's arguments
741  * and relation fields;
742  * else
743  * error
744  * fi
745  *
746  * "e2 must not appear in t initially": this is the general case; the second case
747  * may occur when procedure A calls B and C and when B and C share a global
748  * variable X
749  * which is not seen from A. A may contain relations between B:X and C:X...
750  * See hidden.f in Bugs or Validation...
751  */
752 void
754 {
755  /* updates are performed by side effects */
756  Psysteme s = region_system(reg);
757 
758  pips_assert("region_value_substitute",
759  e1 != entity_undefined && e2 != entity_undefined);
760 
761  /* update only if necessary */
763  {
764  if(!base_contains_variable_p(s->base, (Variable) e2))
765  {
766  sc_variable_rename(s,(Variable) e1, (Variable)e2);
767  }
768  else
769  {
770  pips_internal_error("conflict between e1=%s and e2=%s",
771  entity_name(e1), entity_name(e2));
772  }
773  }
774 }
775 
776 
777 /* list region_entities_cfc_variables(effect reg, list l_ent)
778  * input : a region and a list of entities that may appear in the region
779  * expression.
780  * output : the list of variables that define the initial entities, directly
781  * or indirectly
782  * modifies : nothing
783  * comment : "cfc" stands for "Composante Fortement Connexe"; because
784  * if systems are considered as graphs which vertices are
785  * the constraints and which edges connect constraints
786  * concerning at least one common variable, then this
787  * function searches for the variables contained in
788  * the strongly connected component that also contains
789  * the initial entities.
790  */
792 {
793  return( sc_entities_cfc_variables(region_system(reg), l_ent) );
794 }
795 
796 /* list sc_entities_cfc_variables(Psysteme sc, list l_ent)
797  * input : a system of constraints and a list of entities that may appear
798  * in its constraints.
799  * expression.
800  * output : the list of variables that define the initial entities, directly
801  * or indirectly
802  * modifies : nothing
803  * comment : "cfc" stands for "Composante Fortement Connexe"; because
804  * if systems are considered as graphs which vertices are
805  * the constraints and which edges connect constraints
806  * concerning at least one common variable, then this
807  * function searches for the variables contained in
808  * the strongly connected component that also contains
809  * the initial entities.
810  */
812 {
813  Pcontrainte c, c_pred, c_suiv;
814  Pvecteur v_ent = VECTEUR_NUL, v, v_res = VECTEUR_NUL;
815  list l_res = NIL;
816 
817  if (ENDP(l_ent))
818  return NIL;
819 
820  ifdebug(8) {
821  pips_debug(8, "system: \n");
822  sc_syst_debug(sc);
823  debug(8, "", "variables :\n");
824  print_entities(l_ent);
825  }
826 
827  pips_assert("sc_entities_cfc_variables", !SC_UNDEFINED_P(sc));
828 
829  /* cas particuliers */
830  if(sc_rn_p(sc) || sc_empty_p(sc))
831  /* ne rien faire et renvoyer (nil) */
832  return(NIL);
833 
834  sc = sc_dup(sc);
835 
836  /* we make a vector containing the initial entities */
837  MAP(ENTITY, e,
838  {
839  vect_add_elem(&v_ent, (Variable) e, VALUE_ONE);
840  },
841  l_ent);
842 
843  v_res = vect_dup(v_ent);
844 
845  /* sc has no particularity. We just scan its equalities and inequalities
846  * to find which variables are related to the initial entities */
847  while(vect_common_variables_p((Pvecteur) sc_base(sc), v_res))
848  {
849  /* equalities first */
850  c = sc_egalites(sc);
851  c_pred = (Pcontrainte) NULL;
852  while (c != (Pcontrainte) NULL) {
853  c_suiv = c->succ;
854  /* if a constraint is found in sc, that contains
855  * a variable that already belongs to v_res then this constraint
856  * is removed from sc and its variables are added to v_res */
857  if (vect_common_variables_p(c->vecteur,v_res))
858  {
859  if (c_pred != (Pcontrainte) NULL)
860  c_pred->succ = c_suiv;
861  else
862  sc_egalites(sc) = c_suiv;
863  for(v = c->vecteur; !VECTEUR_NUL_P(v); v = v->succ)
864  {
865  if (vecteur_var(v) != TCST)
867  }
868  }
869  else
870  c_pred = c;
871  c = c_suiv;
872  }
873 
874  /* inequalities then */
875  c = sc_inegalites(sc);
876  c_pred = (Pcontrainte) NULL;
877  while (c != (Pcontrainte) NULL)
878  {
879  c_suiv = c->succ;
880  /* if a constraint is found in sc, that contains a variable that
881  * already belongs to v_res then this constraint is removed from
882  * sc and its variables are added to v_res */
883  if (vect_common_variables_p(c->vecteur,v_res))
884  {
885  if (c_pred != (Pcontrainte) NULL)
886  c_pred->succ = c_suiv;
887  else
888  sc_inegalites(sc) = c_suiv;
889  for(v = c->vecteur; !VECTEUR_NUL_P(v); v = v->succ)
890  {
891  if (vecteur_var(v) != TCST)
893  }
894  }
895  else
896  c_pred = c;
897  c = c_suiv;
898  }
899 
900  /* update sc base */
901  base_rm(sc->base);
902  sc_base(sc) = (Pbase) NULL;
903  (void) sc_creer_base(sc);
904  } /* while */
905 
906  sc_rm(sc);
907  sc = NULL;
908 
909  /* construction of the list of variables. It contains all the variables of
910  * v_res except for the initial entities */
911  for(; !VECTEUR_NUL_P(v_res); v_res = v_res->succ)
912  {
913  entity e = (entity) v_res->var;
914  if (!vect_contains_variable_p(v_ent, (Variable) e))
915  l_res = CONS(ENTITY, e, l_res);
916  }
917 
918  vect_rm(v_res);
919 
920  ifdebug(8) {
921  pips_debug(8, "l_res : \n");
922  print_entities(l_res);
923  }
924 
925  return(l_res);
926 }
927 
928 
929 /*********************************************************************************/
930 /* REGIONS / LISTS OF REGIONS CONVERSION */
931 /*********************************************************************************/
932 
933 /* list region_to_list(reg)
934  * input : a region
935  * output : a list containing this region
936  * modifies : nothing
937  * comment : it does not duplicate the region.
938  */
940 {
941  return(CONS(EFFECT, reg, NIL));
942 }
943 
944 
945 /* list region_to_may_region_list(reg)
946  * input : a region.
947  * output : a list containing the same region with a may approximation
948  * modifies : the initial region
949  * comment : it does not duplicate the region.
950  */
952 effect reg;
953 {
955  return(CONS(EFFECT, reg, NIL));
956 }
957 
958 /* list regions_to_nil_list(reg)
959  * input : a region
960  * output : an empty list of regions
961  * modifies : nothing
962  * comment : for compatibility
963  */
965  region reg2 __attribute__ ((unused)))
966 {
967  return(NIL);
968 }
969 
970 /* list region_to_nil_list(reg)
971  * input : a region
972  * output : an empty list of regions
973  * modifies : nothing
974  * comment : for compatibility
975  */
977 {
978  return(NIL);
979 }
980 
981 
982 /* list regions_to_write_regions(list l_reg)
983  * input : a list of regions.
984  * output : the same list of regions converted to a list of write regions.
985  * modifies : the regions in l_reg are converted to write regions
986  * comment :
987  */
989 {
990  MAP(REGION, reg,
991  {
992  /* Memory leak */
994  },
995  l_reg);
996  return(l_reg);
997 }
998 
999 
1000 /* list regions_read_regions(list l_reg)
1001  * input : a list of regions read and write.
1002  * output : a list of read regions consisting of the read regions
1003  * of the initial list.
1004  * modifies : nothing.
1005  * comment : sharing between the initial and the returned lists components.
1006  */
1008 {
1009  list l_read = NIL;
1010 
1011  MAP(REGION, reg,
1012  {
1013  if (action_read_p(region_action(reg)))
1014  l_read = region_add_to_regions(reg, l_read);
1015  },
1016  l_reg);
1017  return(l_read);
1018 }
1019 
1020 
1021 /* list regions_write_regions(list l_reg)
1022  * input : a list of regions read and write.
1023  * output : a list of write regions consisting of the write regions
1024  * of the initial list.
1025  * modifies : nothing.
1026  * comment : sharing between the initial and the returned lists components.
1027  */
1029 list l_reg;
1030 {
1031  list l_write = NIL;
1032 
1033  MAP(REGION, reg,
1034  {
1035  if (action_write_p(region_action(reg)))
1036  l_write = region_add_to_regions(reg, l_write);
1037  },
1038  l_reg);
1039  return(l_write);
1040 }
1041 
1042 
1043 /****************************************************** CREATION OF REGIONS */
1044 
1045 
1046 reference make_pointed_regions_reference(entity ent, bool indexed_p)
1047 {
1048  list regions_ref_inds = NIL;
1049  int dim;
1050  type ent_ty = ultimate_type(entity_type(ent));
1051  int d = -1;
1052 
1053  if (type_variable_p(ent_ty)) {
1054  /* ent_list_dim = variable_dimensions(type_variable(ent_ty)); */
1055  if(pointer_type_p(ent_ty)) {
1056  /* Are we dealing with the pointer or with the pointed area? */
1057  if(indexed_p) {
1058  /* Only one dimension for pointers when arithmetic is used:
1059  let's hope that subscripts are combined! Unless the pointed type has dimensions... */
1061 
1062  d = type_depth(pt);
1063  if(d==0)
1064  d = 1;
1065  }
1066  else {
1067  d = 0;
1068  }
1069  }
1070  else {
1071  /* Beware, ultimate type does not respect dimensions! */
1072  d = type_depth(entity_type(ent));
1073  }
1074  }
1075 
1076  for (dim = 1; dim <= d; dim++)
1077  regions_ref_inds = gen_nconc(regions_ref_inds,
1078  CONS(EXPRESSION,
1079  make_phi_expression(dim),
1080  NIL));
1081 
1082  /* FI: if I want to add extra-dimensions to reflect structure fields... */
1083 
1084  return make_reference(ent, regions_ref_inds);
1085 }
1086 
1087 /* reference make_regions_reference(entity ent)
1088  * input : a variable entity.
1089  * output : a reference made with the entity ent, and, in case of an array,
1090  * PHI variables as indices.
1091  * modifies : nothing.
1092  */
1094 {
1095  /* The Fortran semantics */
1096  return make_pointed_regions_reference(ent, false);
1097 }
1098 
1099 
1100 /* static predicate make_whole_array_predicate(reference ref)
1101  * input : a variable, which can be either a scalar or an array.
1102  * output : a predicate; its system contains no constraint, but
1103  * the base of the latter contains the phi variables if
1104  * the input variable is an array.
1105  * modifies : nothing;
1106  * comment :
1107  */
1108 static Psysteme make_whole_array_predicate(entity e)
1109 {
1110  Psysteme ps = sc_new();
1112  int d = type_depth(t);
1113 
1114  /* Let's deal with scalar pointers at least */
1115  /* If d==0 and if t is a pointer type, then d is a function of the pointed type */
1116  if(d==0 && pointer_type_p(t)) {
1118  type pt = basic_pointer(tb);
1119 
1120  d = type_depth(pt);
1121  }
1122 
1123  /* No phi if the entity has no depth (includes scalar entity which have depth 0 */
1124  if (d>0)
1125  {
1126  int dim;
1127 
1128  /* add phi variables in the base */
1129  for (dim = 1; dim<=d; dim ++)
1130  {
1131  entity phi = make_phi_entity(dim);
1132  sc_base_add_variable(ps, (Variable) phi);
1133  }
1134 
1135  /* add array bounds if asked for */
1136  /* FI: To be improved for arrays embedded within structures. */
1137  if (array_bounds_p())
1138  ps = sc_safe_append(ps,
1140  }
1141  return ps;
1142 }
1143 
1144 
1145 /**
1146  for C modules, the reference is trusted. for Fortran modules, if
1147  the number of indices is less than the number of declared
1148  dimensions, it is assumed that it's a reference to the whole
1149  (sub-)array, and array bounds are added for the lacking
1150  dimensions.
1151 
1152  @param ref is a reference
1153  @param tac is an action tag (read or write)
1154  tac don't have to be use by another effects (make a copy)
1155  @return an effect representing a region corresponding to the reference.
1156 
1157  */
1159 {
1161  effect reg;
1162  bool linear_p = true;
1163  Psysteme sc;
1164 
1166  {
1167  pips_debug(3, "Reference : \"%s\"",
1169  reg = make_region(make_reference(e, NIL),
1170  tac,
1172  sc_new());
1173  }
1174  else
1175  {
1176 
1178  int d = effect_type_depth(bct), dim;
1179  bool pointer_p = pointer_type_p(bct);
1180  list reg_ref_inds = NIL;
1181 
1182  /* first make the predicate according to ref */
1183 
1184  ifdebug(3)
1185  {
1186  pips_debug(3, "Reference : \"%s\"",
1188  fprintf(stderr, "(it's %s a pointer)\n", pointer_p?"":"not");
1189  pips_debug(3,"effect type depth is %d\n", d);
1190  }
1191 
1192  if (dummy_parameter_entity_p(e))
1193  pips_internal_error("the input reference entity is a dummy parameter (%s)",
1194  entity_name(e));
1195 
1196  /* FI: If t is a pointer type, then d should depend on the type_depth
1197  of the pointed type... */
1198  if (d>0 || pointer_p)
1199  {
1200  int idim;
1201  list ind = reference_indices(ref);
1202  int n_ind = gen_length(ind);
1203  int max_phi = 0;
1204  /* imported from preprocessor.h */
1205 
1206  pips_debug(8, "pointer or array or struct case \n");
1207 
1208  pips_assert("The number of indices is less or equal to the possible "
1209  "effect type depth, unless we are dealing with a pointer.\n",
1210  (int) gen_length(ind) <= d || pointer_p);
1211 
1213  && n_ind < d)
1214  {
1215  /* dealing with whole array references as in TAB = 1.0 */
1216  sc = entity_declaration_sc(e);
1217  max_phi = d;
1218  }
1219  else
1220  {
1221  sc = sc_new();
1222  max_phi = n_ind;
1223  }
1224 
1225  list sl = reference_indices(ref);
1226  for (dim = 1; dim <= max_phi; dim++) {
1228  if(!ENDP(sl)) {
1229  expression s = EXPRESSION(CAR(sl));
1230  POP(sl);
1231  if(field_expression_p(s))
1232  ns = copy_expression(s);
1233  else
1234  ns = make_phi_expression(dim);
1235  }
1236  else {
1237  // As it may occur in Fortran IO for instance
1238  ns = make_phi_expression(dim);
1239  }
1240  reg_ref_inds = gen_nconc(reg_ref_inds,
1241  CONS(EXPRESSION,
1242  ns,
1243  NIL));
1244  }
1245 
1246  pips_assert("sc is weakly consistent", sc_weak_consistent_p(sc));
1247 
1248  /* we add the constraints corresponding to the reference indices */
1249  for (idim = 1; ind != NIL; idim++, ind = CDR(ind))
1250  {
1251  /* For equalities. */
1252  expression exp_ind = EXPRESSION(CAR(ind));
1253  bool dim_linear_p = false;
1254  bool unbounded_p = unbounded_expression_p(exp_ind);
1255  bool field_p = field_expression_p(exp_ind);
1256 
1257  ifdebug(3)
1258  {
1259  if (unbounded_p)
1260  pips_debug(3, "unbounded dimension PHI%d\n",idim);
1261  else
1262  pips_debug(3, "addition of equality :\nPHI%d - %s = 0\n",
1263  idim, expression_to_string(exp_ind));
1264  }
1265 
1266  if (unbounded_p)
1267  {
1268  /* we must add PHI_idim in the Psystem base */
1269  entity phi = make_phi_entity(idim);
1270  sc_base_add_variable(sc, (Variable) phi);
1271  dim_linear_p = false;
1272  }
1273  else if(field_p) {
1274  dim_linear_p = true;
1275  }
1276  else
1277  {
1278  pips_assert("sc is weakly consistent", sc_weak_consistent_p(sc));
1279  dim_linear_p =
1280  sc_add_phi_equation(&sc, exp_ind, idim, IS_EG, PHI_FIRST);
1281 
1282  pips_assert("sc is weakly consistent", sc_weak_consistent_p(sc));
1283  pips_debug(3, "%slinear equation.\n", dim_linear_p? "": "non-");
1284  }
1285  linear_p = linear_p && dim_linear_p;
1286  } /* for */
1287 
1288  pips_assert("sc is weakly consistent", sc_weak_consistent_p(sc));
1289 
1290  /* add array bounds if asked for */
1291  if (array_bounds_p()) {
1292  sc = sc_safe_append(sc,
1294  pips_assert("sc is weakly consistent", sc_weak_consistent_p(sc));
1295  }
1296 
1297  } /* if (d>0 || pointer_p) */
1298 
1299  else
1300  {
1301  pips_debug(8, "non-pointer scalar type\n");
1302  sc = sc_new();
1303  }/* if else */
1304 
1305  pips_assert("sc is weakly consistent", sc_weak_consistent_p(sc));
1306 
1307  /* There was a preference originally : let's try a reference since a new
1308  reference is built for each region. BC */
1309  reg = make_region(
1310  make_reference(reference_variable(ref), reg_ref_inds),
1311  tac,
1314  UU),
1315  sc);
1316  }
1318 
1319  ifdebug(3)
1320  {
1321  pips_debug(3, "end : region is :\n");
1322  print_region(reg);
1323  }
1324  return(reg);
1325 }
1326 
1327 /* reference make_regions_psi_reference(entity ent)
1328  * input : a variable entity.
1329  * output : a reference made with the entity ent, and, in case of an array,
1330  * PSI variables as indices.
1331  * modifies : nothing.
1332  */
1334 {
1335  list regions_ref_inds = NIL, ent_list_dim = NIL;
1336  int dim;
1337  type ent_ty = entity_type(ent);
1338 
1339  if (type_variable_p(ent_ty))
1340  ent_list_dim = variable_dimensions(type_variable(ent_ty));
1341 
1342  if (! entity_scalar_p(ent))
1343  for (dim = 1; ent_list_dim != NIL; ent_list_dim = CDR(ent_list_dim), dim++)
1344  regions_ref_inds = gen_nconc(regions_ref_inds,
1345  CONS(EXPRESSION,
1346  make_psi_expression(dim),
1347  NIL));
1348 
1349  return(make_reference(ent, regions_ref_inds));
1350 }
1351 
1352 
1353 /* effect reference_whole_region(reference ref, action tac, tap)
1354  * input : a variable reference, and the action of the region.
1355  * output : a region representing the entire memory space allocated
1356  * to the variable *reference* (and not entity, this is useful
1357  * for partially subscripted arrays, as is the case for
1358  * PRINT *, A, where A is an array, see for instance
1359  * Regions/incr3. BC).
1360  * the systeme of constraints is a sc_rn(phi_1, ..., phi_n)
1361  * except if REGIONS_WITH_ARRAY_BOUNDS is true.
1362  * The resulting region is a MUST region if everything is linear,
1363  * MAY otherwise. It's the responsibility of the caller to change it
1364  * according to the calling context. (BC).
1365  * modifies : nothing.
1366  */
1368 {
1370  type t = entity_type(e);
1371  int d = type_depth(t), dim;
1372  bool linear_p = true;
1373  Psysteme sc;
1374  bool pointer_p = pointer_type_p(ultimate_type(t));
1375 
1376  effect reg = effect_undefined;
1377  list reg_ref_inds = NIL;
1378 
1379  ifdebug(3)
1380  {
1381  pips_debug(3, "Reference : \"%s\"",
1383  fprintf(stderr, "(it's %s a pointer)\n", pointer_p?"":"not");
1384  pips_debug(3,"type depth is %d\n", d);
1385  }
1386 
1387  /* FI: If t is a pointer type, then d should depend on the type_depth
1388  of the pointed type... */
1389  if (d>0 || pointer_p)
1390  {
1391  int idim;
1392  list ind = reference_indices(ref);
1393  int n_ind = gen_length(ind);
1394 
1395  pips_debug(8, "pointer or array case \n");
1396 
1397  pips_assert("The number of indices is less or equal to the type depth, "
1398  "unless we are dealing with a pointer",
1399  (int) gen_length(ind) <= d || pointer_p);
1400 
1401 
1402  if (n_ind < d)
1403  sc = entity_declaration_sc(e);
1404  else
1405  sc = make_whole_array_predicate(e);
1406 
1407  for (dim = 1; dim <= d; dim++)
1408  reg_ref_inds = gen_nconc(reg_ref_inds,
1409  CONS(EXPRESSION,
1410  make_phi_expression(dim),
1411  NIL));
1412 
1413  /* we add the constraints corresponding to the reference indices */
1414  for (idim = 1; ind != NIL; idim++, ind = CDR(ind))
1415  {
1416  /* For equalities. */
1417  expression exp_ind = EXPRESSION(CAR(ind));
1418  bool dim_linear_p;
1419  bool unbounded_p = unbounded_expression_p(exp_ind);
1420 
1421  ifdebug(3)
1422  {
1423  if (unbounded_p)
1424  pips_debug(3, "unbounded dimension PHI%d\n",idim);
1425  else
1426  pips_debug(3, "addition of equality :\nPHI%d - %s = 0\n",
1427  idim,
1428  expression_to_string(exp_ind));
1429  }
1430 
1431  if (unbounded_p)
1432  {
1433  /* we must add PHI_idim in the Psystem base */
1434  entity phi = make_phi_entity(idim);
1435  sc_base_add_variable(sc, (Variable) phi);
1436  dim_linear_p = false;
1437  }
1438  else
1439  {
1440 
1441  dim_linear_p =
1442  sc_add_phi_equation(&sc, exp_ind, idim, IS_EG, PHI_FIRST);
1443 
1444  pips_debug(3, "%slinear equation.\n", dim_linear_p? "": "non-");
1445  }
1446  linear_p = linear_p && dim_linear_p;
1447  } /* for */
1448  } /* if (d>0 || pointer_p) */
1449 
1450  else
1451  {
1452  pips_debug(8, "non-pointer scalar type\n");
1453  sc = sc_new();
1454  }/* if else */
1455 
1456  reg = make_region(
1457  make_reference(reference_variable(ref), reg_ref_inds),
1458  copy_action(tac),
1461  UU),
1462  sc);
1464 
1465  ifdebug(3)
1466  {
1467  pips_debug(3, "end : region is :\n");
1468  print_region(reg);
1469  }
1470  return(reg);
1471 
1472 }
1473 
1475 {
1476  region new_eff;
1477  action ac = copy_action(tac);
1479 
1480  new_eff = make_region(make_regions_reference(e), ac, ap,
1481  make_whole_array_predicate(e));
1482  return(new_eff);
1483 }
1484 
1485 
1486 /* list region_to_store_independent_region_list(effect reg, bool force_may_p)
1487  * input : a region and a boolean;
1488  * output : a list with a unique region representing the entire memory space
1489  * allocated to the variable reference : the systeme of constraints
1490  * is a sc_rn(phi_1, ..., phi_n) except if REGIONS_WITH_ARRAY_BOUNDS
1491  * is true. The region is a MAY region.
1492  * The bool force_may_p is here for consistency with
1493  * effect_to_store_independent_sdfi_list.
1494  * We could refine this function in order to keep constraints
1495  * which are independent from the store.
1496  * modifies : nothing.
1497  */
1499  bool __attribute__ ((unused)) force_may_p)
1500 {
1503  return(CONS(EFFECT,eff,NIL));
1504 }
1505 
1506 
1507 /* void convex_region_add_expression_dimension(effect reg, expression exp)
1508  * input : a convex region and an expression
1509  * output : nothing
1510  * modifies : the region reg, and normalizes the expression
1511  * comment : adds a last dimension phi_last to the region. If the expression
1512  * is normalizable, also adds a constraint phi_last = exp. Else,
1513  * changes the approximation into may.
1514  */
1516 {
1517  cell reg_c = effect_cell(reg);
1518  reference ref;
1519  int dim;
1520  bool dim_linear_p;
1521 
1522  ifdebug(8)
1523  {
1524  pips_debug(8, "begin with region :\n");
1525  print_region(reg);
1526  }
1527 
1528  pips_assert("region cell must be a reference\n", cell_reference_p(reg_c));
1529 
1530  ref = cell_reference(reg_c);
1531 
1532  /* first add a new PHI dimension to the region reference */
1533  dim = gen_length(reference_indices(ref))+1;
1534 
1535  pips_debug(8, "add PHI_%d\n", dim);
1537  CONS(EXPRESSION,
1538  make_phi_expression(dim),
1539  NIL));
1540 
1541  /* Then add the corresponding constraint to the Psystem */
1542  dim_linear_p =
1544 
1545  if (!dim_linear_p)
1546  {
1547  pips_debug(8, "non linear expression : change approximation to may\n");
1549  }
1550  ifdebug(8)
1551  {
1552  pips_debug(8, "end with region :\n");
1553  print_region(reg);
1554  pips_assert("the region is consistent", effect_consistent_p(reg));
1555  }
1556 
1557  return;
1558 }
1559 
1560 /**
1561  eliminate phi_i from the region Psystem, and adds the constraint
1562  phi_i==exp if exp is normalizable.
1563 
1564  @param reg a convex region
1565  @param exp the new expresion for the region ith dimension
1566  @param i is the rank of the dimension to change.
1567 
1568  */
1570  int i)
1571 {
1572  list l_phi_i = CONS(ENTITY,make_phi_entity(i),NIL);
1573  bool dim_linear_p;
1574 
1575  /* first eliminate PHI_i variable from the system */
1577  gen_free_list(l_phi_i);
1578 
1579  /* then add the new constraint in the system if the expression exp
1580  is not unbounded */
1582  {
1583  pips_debug(8, "unbounded expression \n");
1585  }
1586  else
1587  {
1588  dim_linear_p =
1590 
1591  if (!dim_linear_p)
1592  {
1593  pips_debug(8, "non linear expression : change approximation to may\n");
1595  }
1596  }
1597 
1598  ifdebug(8)
1599  {
1600  pips_debug(8, "end with region :\n");
1601  print_region(reg);
1602  pips_assert("the region is consistent", effect_consistent_p(reg));
1603  }
1604 
1605  return;
1606 }
1607 
1608 /**
1609  eliminate phi_i from the region Psystem.
1610 
1611  @param reg a convex region
1612  @param exp the new expresion for the region ith dimension
1613  @param i is the rank of the dimension to change.
1614 
1615  */
1617 {
1618  list l_phi_i = CONS(ENTITY,make_phi_entity(i),NIL);
1619 
1620  /* first eliminate PHI_i variable from the system */
1622  gen_free_list(l_phi_i);
1623 
1624  ifdebug(8)
1625  {
1626  pips_debug(8, "end with region :\n");
1627  print_region(reg);
1628  pips_assert("the region is consistent", effect_consistent_p(reg));
1629  }
1630 
1631  return;
1632 }
1633 
1634 
1635 
1636 
1637 /**
1638  @brief copies the input_effect and converts all it's reference indices that refer to
1639  field entities to a phi variable, and add the corresponding constraint
1640  (PHI_x == rank) in the descriptor system, rank being the integer corresponding
1641  to the field rank in the field list of the ancestor derived type.
1642  @input input_effect is a convex effect, and is not modified.
1643  @return a new effect.
1644  */
1646 {
1647  effect eff = copy_effect(input_effect);
1648  cell c = effect_cell(input_effect);
1649  /* if it's a preference, we are sure there are no field dimensions */
1650  if (cell_reference_p(c))
1651  {
1652  reference r = cell_reference(c);
1653  list l_ind = reference_indices(r);
1654  int dim = 1;
1655 
1656  FOREACH(EXPRESSION, ind, l_ind)
1657  {
1658  syntax s = expression_syntax(ind);
1659  if (syntax_reference_p(s))
1660  {
1662  if (entity_field_p(ind_e))
1663  {
1664  int rank = entity_field_rank(ind_e);
1665  expression rank_exp = int_to_expression(rank);
1666 
1667  /* first change the effect reference index */
1668  expression new_ind = make_phi_expression(dim);
1669  free_syntax(s);
1671  free_expression(new_ind);
1672  /* Then add the constrain PHI_rank == rank into the effect system */
1673  (void)sc_add_phi_equation(&region_system(eff), rank_exp, dim, IS_EG, PHI_FIRST);
1674  free_expression(rank_exp);
1675  }
1676  }
1677  dim++;
1678  } /* FOREACH*/
1679  }
1680  return eff;
1681 }
1682 
1683 
1684 /**
1685 
1686  @param eff1 and eff2 are convex regions.
1687  @return eff1 (which is modified) : the reference indices of eff2
1688  (accordingly shifted) are appended to the reference indices of eff1 ;
1689  and the Psystem of eff2 is appended to eff1 after renaming of phi
1690  variables.
1691  */
1692 effect region_append(effect eff1, effect eff2)
1693 {
1694  list l_ind_1 = reference_indices(effect_any_reference(eff1));
1695  int nb_phi_1 = (int) gen_length(l_ind_1);
1696 
1697  list l_ind_2 = reference_indices(effect_any_reference(eff2));
1698  int nb_phi_2 = (int) gen_length(l_ind_2);
1699 
1700  Psysteme sc2 = region_system(eff2);
1701 
1702  int i;
1703 
1704  ifdebug(8) {
1705  pips_debug(8, "begin with regions : \n");
1706  print_region(eff1);
1707  print_region(eff2);
1708  pips_debug(8, "nb_phi1 = %d, nb_phi_2 = %d \n", nb_phi_1, nb_phi_2);
1709  }
1710 
1711 
1712  for(i=1; i<= nb_phi_2; i++)
1713  {
1714  expression ind_exp_2 = EXPRESSION(CAR(l_ind_2));
1715  if (entity_field_p(expression_variable(ind_exp_2)))
1716  l_ind_1 = gen_nconc(l_ind_1,
1717  CONS(EXPRESSION,
1718  copy_expression(ind_exp_2),
1719  NIL));
1720  else
1721  l_ind_1 = gen_nconc(l_ind_1,
1722  CONS(EXPRESSION,
1723  make_phi_expression(nb_phi_1+i),
1724  NIL));
1725  POP(l_ind_2);
1726  }
1727  reference_indices(effect_any_reference(eff1)) = l_ind_1;
1728 
1729  if(nb_phi_1 >0)
1730  {
1731  for(i=nb_phi_2; i>=1; i--)
1732  {
1733  entity old_phi = make_phi_entity(i);
1734  entity new_phi = make_phi_entity(nb_phi_1+i);
1735 
1736  sc_variable_rename(sc2, old_phi, new_phi);
1737  }
1738  }
1739 
1740  region_sc_append(eff1, sc2, true);
1741 
1742  effect_approximation_tag(eff1) =
1744  effect_approximation_tag(eff2));
1745 
1746  ifdebug(8) {
1747  pips_debug(8, "returning : \n");
1748  print_region(eff1);
1749  }
1750  return(eff1);
1751 }
1752 
1753 
1754 ␌
1755 /************************************************************ PHI ENTITIES */
1756 
1757 /* entity make_phi_entity(int n)
1758  * input : an integer n giving the range of the PHI entity.
1759  * output : the entity PHI_n.
1760  * modifies : phi[] (eventually).
1761  * comment : finds or generates an entity representing a region descriptor
1762  * of indice n.
1763  * A region descriptor representes the value domain of one dimension
1764  * of an array, this dimension is represented by the indice.
1765  * Fortran accepts a maximum of 7 dimensions.
1766  *
1767  * Once a region descriptor is created, it is stored into a static array
1768  * (phi[]); thus, each next time a region descriptor entity is needed,
1769  * it is just picked up in phi[].
1770  * If the region descriptor is not in phi[], it may be in the table
1771  * where all entities are stored, because of previous computations.
1772  * At last, if it is not found there, it is created.
1773  */
1774 entity make_phi_entity(int n)
1775 {
1776  pips_assert("phi index between 1 and NB_MAX_ARRAY_DIM\n", 1<=n && n<=NB_MAX_ARRAY_DIM);
1777 
1778  /* phi indices are between 1 to NB_MAX_ARRAY_DIM. array indices are between 0 to NB_MAX_ARRAY_DIM-1. */
1779  if (phi[n-1] == entity_undefined)
1780  {
1781  entity v;
1782  char phi_name[6];
1783  char * s;
1784 
1785  pips_assert ("n can't be more than a two digit number", n < 100);
1786  pips_assert ("PHI_PREFIX lenght has been changed", strlen (PHI_PREFIX) == 3);
1787 
1788  (void) strcpy(phi_name, PHI_PREFIX);
1789  (void) sprintf(phi_name+3,"%d",n);
1791  MODULE_SEP_STRING, phi_name, (char *) NULL));
1792 
1794  {
1797  value_undefined);
1798  }
1799  phi[n-1] = v;
1800  }
1801 
1802  return (phi[n-1]);
1803 }
1804 
1805 /* Returns the number of a phi entity, i.e. phi =
1806  * make_phi_entity(phi_entity_rank(phi))
1807  *
1808  * rank in [1.. NB_MAX_ARRAY_DIM], which may not be enough for
1809  * points-to references...
1810  *
1811  * In case of failure, return 0.
1812  */
1813 int phi_entity_rank(entity phi)
1814 {
1815 
1816  int rank = 0;
1817  // We could also check the package name
1818  string ln = (string) entity_local_name(phi);
1819  if(strncmp(ln, PHI_PREFIX, 3)==0) {
1820  string rn = ln+3;
1821  int n = sscanf(rn, "%d", &rank);
1822  if(n!=1)
1823  rank = 0;
1824  }
1825  return rank;
1826 }
1827 
1828 list phi_entities_list(int phi_min, int phi_max)
1829 {
1830  list l_phi = NIL;
1831  int i;
1832 
1833  for(i=phi_min; i<=phi_max; i++)
1834  l_phi = gen_nconc(l_phi, CONS(ENTITY, make_phi_entity(i), NIL));
1835 
1836  return(l_phi);
1837 }
1838 
1839 /* Returns the list of phi variables used as subscript in effect eff */
1841 {
1842  list phi_l = NIL;
1844  list sl = reference_indices(r);
1845  FOREACH(EXPRESSION, se, sl) {
1846  syntax ss = expression_syntax(se); //subscript syntax
1847  if(syntax_reference_p(ss)) {
1848  reference sr = syntax_reference(ss);
1849  entity phi = reference_variable(sr);
1850  int r = phi_entity_rank(phi);
1851  if(r>0)
1852  phi_l = CONS(ENTITY, phi, phi_l);
1853  }
1854  }
1855  phi_l = gen_nreverse(phi_l);
1856  return phi_l;
1857 }
1858 
1859 /* expression make_phi_expression(int n)
1860  * input : the range of the PHI entity to create.
1861  * output : an expression made of a PHI variable of range n;
1862  * modifies : nothing.
1863  */
1865 {
1866  entity phi;
1867  reference ref;
1868  syntax synt;
1869  expression exp;
1870 
1871  phi = make_phi_entity(n);
1872  ref = make_reference(phi, NIL);
1875 
1876  return(exp);
1877 }
1878 
1879 
1880 
1881 
1882 /* bool sc_add_phi_equation(Psysteme * psc, expression expr,
1883  * int dim, bool is_eg, bool is_phi_first)
1884  *
1885  * input : a region predicate, an expression caracterizing a PHI
1886  * variable of range dim, two booleans indicating if the
1887  * equation to create is an equality or an inequality, and
1888  * this last case, the direction of the inequality.
1889  *
1890  * output : true if expr is linear, false otherwise, which means that
1891  * sc does not contain all the information associated to expr
1892  * (MAY region).
1893  *
1894  * modifies : adds an equation containing a PHI variable to the system
1895  * of constraints given in argument.
1896  *
1897  * comment : The equation can, in fact, be an equality or an inequality :
1898  *
1899  * If it is an equality (is_eg == true) :
1900  * PHI - expr = 0
1901  * If it is an inequality (is_eg == false) :
1902  * (is_phi_first == false) expr - PHI <= 0
1903  * (is_phi_first == true ) PHI - expr <= 0
1904  *
1905  * The indice of the region descriptor (PHI) is given by
1906  * "dim". The equation is added only if the expression
1907  * (expr) is a normalized linear one, compatible with the
1908  * semantics analysis.
1909  *
1910  * Note : the basis of the system sc is updated.
1911  *
1912  * Warning: this function may return wrong results when
1913  * expressions used as subscripts have side-effects. Also
1914  * this function would return more precise results if
1915  * information about the store in which the expression is
1916  * evaluated were passed. The problem exists in
1917  * reference_to_convex_region() and in
1918  * generic_p_proper_effect_of_reference().
1919  */
1920 bool sc_add_phi_equation(Psysteme *psc, expression expr, int dim, bool is_eg,
1921  bool is_phi_first)
1922 {
1923  if(expression_range_p(expr)) {
1924  pips_assert("inequality with respect to a range has no meaning",is_eg);
1925  range r =expression_range(expr);
1926  bool must_p = sc_add_phi_equation(psc, range_upper(r), dim, false, is_phi_first);
1927  must_p &= sc_add_phi_equation(psc, range_lower(r), dim, false, !is_phi_first);
1928  return must_p;
1929  }
1930  else {
1931  normalized nexpr = NORMALIZE_EXPRESSION(expr);
1932 
1933  bool must_p = false; /* Do we capture the semantics of the
1934  subscript expression exactly for sure? */
1935  Psysteme sc = *psc;
1936 
1937  /* Nga Nguyen: 29 August 2001
1938  Add a value mapping test => filter variables that are not analysed by semantics analyses
1939  such as equivalenced variables. If not, the regions will be false (see bugregion.f)
1940  Attention: value hash table may not be defined */
1941 
1942  pips_assert("sc is weakly consistent", SC_UNDEFINED_P(sc) || sc_weak_consistent_p(sc));
1943 
1944  if (normalized_linear_p(nexpr)) {
1945  Pvecteur v2 = vect_copy(normalized_linear(nexpr));
1946 
1948  entity phi = make_phi_entity(dim);
1949  Pvecteur v1 = vect_new((Variable) phi, VALUE_ONE);
1950  Pvecteur vect;
1951 
1952  if (is_phi_first)
1953  vect = vect_substract(v1, v2);
1954  else
1955  vect = vect_substract(v2, v1);
1956 
1957  vect_rm(v1);
1958  /* vect_rm(v2); */
1959 
1960  if(!VECTEUR_NUL_P(vect))
1961  {
1962  pips_assert("sc is defined", !SC_UNDEFINED_P(sc));
1963 
1964  if (is_eg)
1965  {
1966  sc_add_egalite(sc, contrainte_make(vect));
1967  }
1968  else
1969  {
1970  sc_add_inegalite(sc, contrainte_make(vect));
1971  }
1972 
1973  /* The basis of sc has to be updated with the new entities
1974  introduced with the constraint addition. */
1975  for(; !VECTEUR_NUL_P(vect); vect = vect->succ)
1976  if(vect->var != TCST)
1977  sc->base = vect_add_variable(sc->base, vect->var);
1978 
1979  sc->dimension = vect_size(sc->base);
1980  }
1981 
1982  must_p = true;
1983  }
1984  else {
1985  /* Some variables are not analyzed by semantics, for instance
1986  because they are statically aliased in a non-analyzed way */
1987  /* No information about this subscript expression is added in
1988  the region. */
1989  vect_rm(v2);
1990  must_p = false;
1991  }
1992  }
1993  else /* the expression is not linear */ {
1994  if(is_eg) {
1995  /* try to see if expression is i++, i--, ++i, --i */
1996 
1997  if(expression_call_p(expr))
1998  {
1999  call c = syntax_call(expression_syntax(expr));
2000  entity op = call_function(c);
2001  list args = call_arguments(c);
2002 
2003  if(ENTITY_POST_INCREMENT_P(op) ||
2005  {
2006  return sc_add_phi_equation(psc, EXPRESSION(CAR(args)), dim, is_eg, is_phi_first);
2007  }
2008  else if (ENTITY_PRE_INCREMENT_P(op) )
2009  {
2010  expression new_exp = MakeBinaryCall(CreateIntrinsic("+"),
2012  must_p = sc_add_phi_equation(psc, new_exp, dim, is_eg, is_phi_first);
2013  free_expression(new_exp);
2014  return must_p;
2015  }
2016  else if (ENTITY_PRE_DECREMENT_P(op))
2017  {
2018  expression new_exp = MakeBinaryCall(CreateIntrinsic("-"),
2020  must_p = sc_add_phi_equation(psc, new_exp, dim, is_eg, is_phi_first);
2021  free_expression(new_exp);
2022  return must_p;
2023  }
2024 
2025  }
2026 
2027 
2028  /* Nga Nguyen: 29 August 2001
2029  If the expression expr is not a linear expression, we try to retrieve more
2030  information by using function any_expression_to_transformer, for cases like:
2031 
2032  ITAB(I/2) => {2*PHI1 <= I <= 2*PHI1+1}
2033  ITAB(MOD(I,3)) => {0 <= PHI1 <= 2}, ...
2034 
2035  The function any_expression_to_transformer() returns a transformer that may
2036  contain temporary variables so we have to project these variables.
2037 
2038  The approximation will become MAY (although in some cases, it is MUST) */
2039 
2040  entity phi = make_phi_entity(dim);
2041 
2045  // FI: this should be checked for memory leaks
2046  prec = transformer_identity();
2047  else
2048  {
2050  // No need for information about previous variable updates
2051  prec = transformer_range(p);
2052  }
2053 
2054  // transformer trans = any_expression_to_transformer(phi,expr,transformer_identity(),true);
2055  transformer trans = any_expression_to_transformer(phi,expr,prec,true);
2056 
2057  // FI: prec should be freed here I believe
2058 
2059  must_p = false;
2060 
2061  /* Careful: side-effects are lost */
2062  if (!transformer_undefined_p(trans)) {
2063  if(!ENDP(transformer_arguments(trans))) {
2064  string e = expression_to_string(expr);
2066  "Side-effects in subscript expression \"%s\" should be avoided:\n", e);
2067  free(e);
2068  }
2070 
2071  /* Is the phi variable constrained by an equation? an
2072  * inequality? nothing?
2073  */
2074  if(transformer_equations_constrain_variable_p(new_trans, phi))
2075  must_p = true;
2076  else if(transformer_inequalities_constrain_variable_p(new_trans, phi)) {
2077  string e = expression_to_string(expr);
2079  "Imprecise subscript expression \"%s\" should be avoided:\n", e);
2080  free(e);
2081  }
2082  else {
2083  string e = expression_to_string(expr);
2085  "No information derived from subscript expression \"%s\":\n", e);
2086  free(e);
2087  }
2088 
2089 
2090  /* Add the new constraint to the convex array region being built. */
2091  Psysteme p_trans = sc_copy(predicate_system(transformer_relation(new_trans)));
2092 
2093  /* trans has been transformed into new_trans by the
2094  projection */
2095  //free_transformer(trans);
2096  free_transformer(new_trans);
2097  /* When sc is Rn, sc is not updated but freed and a copy of
2098  p_trans is returned. */
2099  sc = sc_safe_append(sc, p_trans);
2100  }
2101  }
2102  else {
2103  /* An inequation should be generated.
2104  *
2105  * We end up here, for instance, with an unbounded
2106  * dimension. but we could also have a non-linear
2107  * declaration such as t[n*n];
2108  */
2109  pips_user_warning("Case not implemented as well as it could be\n");
2110  must_p = false;
2111  }
2112  }
2113  pips_assert("sc is weakly consistent", sc_weak_consistent_p(sc));
2114  *psc = sc;
2115  return must_p;
2116  }
2117 }
2118 
2119 
2120 /* void phi_first_sort_base(Pbase base)
2121  * input : the base of a region
2122  * output : nothing.
2123  * modifies : *ppbase.
2124  * comment : sorts the base such that the PHI variables come first.
2125  * it is usefull for the convex_hull, to preserve the form
2126  * of the predicate.
2127  */
2128 void phi_first_sort_base(Pbase *ppbase)
2129 {
2130  Pvecteur v, v_pred = VECTEUR_NUL;
2131  bool first = true, phi_only = true;
2132 
2133  ifdebug(8) {
2134  pips_debug(8, "initial base :\n");
2135  vect_debug(*ppbase);
2136  }
2137 
2138  for( v = (Pvecteur) *ppbase; !VECTEUR_NUL_P(v); v = v->succ)
2139  {
2140  /* if a PHI variable is encountered, and if it is not the first term
2141  * of the base, or it is not preceded only by PHI variables, then
2142  * we put it at the head of the vector. */
2143  if (strncmp(entity_name((entity) v->var), REGIONS_MODULE_NAME, 10) == 0)
2144  {
2145  if (phi_only)
2146  {
2147  v_pred = v;
2148  if (first) first = false;
2149  }
2150  else
2151  {
2152  v_pred->succ = v->succ;
2153  v->succ = (Pvecteur) *ppbase;
2154  *ppbase = v;
2155  v = v_pred;
2156  }
2157  }
2158  else
2159  {
2160  if (phi_only)
2161  {
2162  first = false;
2163  phi_only = false;
2164  }
2165  v_pred = v;
2166  }
2167 
2168  } /* for */
2169 
2170  ifdebug(8) {
2171  pips_debug(8, "final base :\n");
2172  vect_debug(*ppbase);
2173  }
2174 }
2175 
2176 
2177 /* int base_nb_phi(Pbase b)
2178  * input : a base
2179  * output : the number of phi variables in this base.
2180  * modifies : nothing.
2181  * comment :
2182  */
2183 int base_nb_phi(Pbase b)
2184 {
2185  int n_phi = 0;
2186 
2187  for(; !VECTEUR_NUL_P(b); b = b->succ)
2188  {
2189  if (!term_cst(b))
2190  if (variable_phi_p((entity) var_of(b))) n_phi++;
2191  }
2192 
2193  return(n_phi);
2194 }
2195 ␌
2196 /*********************************************************************************/
2197 /* PSY ENTITIES */
2198 /*********************************************************************************/
2199 
2200 /* entity make_psi_entity(int n)
2201  * input : an integer n giving the range of the PHI entity.
2202  * output : the entity PHI_n.
2203  * modifies : psi[] (eventually).
2204  * comment : finds or generates an entity representing a region descriptor
2205  * of indice n.
2206  * A region descriptor representes the value domain of one dimension
2207  * of an array, this dimension is represented by the indice.
2208  * Fortran accepts a maximum of 7 dimensions.
2209  *
2210  * Once a region descriptor is created, it is stored into a static array
2211  * (psi[]); thus, each next time a region descriptor entity is needed,
2212  * it is just picked up in psi[].
2213  * If the region descriptor is not in psi[], it may be in the table
2214  * where all entities are stored, because of previous computations.
2215  * At last, if it is not found there, it is created.
2216  */
2217 entity make_psi_entity(int n)
2218 {
2219  pips_assert("psy index between 1 and NB_MAX_ARRAY_DIM\n", 1<=n && n<=NB_MAX_ARRAY_DIM);
2220 
2221  /* psi indices are between 1 to NB_MAX_ARRAY_DIM. Array indices are between 0 to NB_MAX_ARRAY_DIM-1. */
2222  if (psi[n-1] == entity_undefined)
2223  {
2224  entity v;
2225  char psi_name[6];
2226  char * s;
2227 
2228  pips_assert ("n can't be more than a two digit number", n < 100);
2229  pips_assert ("PSI_PREFIX lenght has been changed", strlen (PSI_PREFIX) == 3);
2230 
2231  (void) strcpy(psi_name, PSI_PREFIX);
2232  (void) sprintf(psi_name+3,"%d",n);
2234  MODULE_SEP_STRING, psi_name, (char *) NULL));
2235 
2237  {
2238  v = make_entity(s,
2241  value_undefined);
2242  }
2243 
2244  psi[n-1] = v;
2245  }
2246  return (psi[n-1]);
2247 }
2248 
2249 
2250 list psi_entities_list(int psi_min, int psi_max)
2251 {
2252  list l_psi = NIL;
2253  int i;
2254 
2255  for(i=psi_min; i<=psi_max; i++)
2256  l_psi = gen_nconc(l_psi, CONS(ENTITY, make_psi_entity(i), NIL));
2257 
2258  return(l_psi);
2259 }
2260 
2261 
2262 /* expression make_psi_expression(int n)
2263  * input : the range of the PHI entity to create.
2264  * output : an expression made of a PHI variable of range n;
2265  * modifies : nothing.
2266  */
2268 {
2272 }
2273 
2274 
2275 /* int base_nb_psi(Pbase b)
2276  * input : a base
2277  * output : the number of psi variables in this base.
2278  * modifies : nothing.
2279  * comment :
2280  */
2281 int base_nb_psi(Pbase b)
2282 {
2283  int n_psi = 0;
2284 
2285  for(; !VECTEUR_NUL_P(b); b = b->succ)
2286  if (variable_psi_p((entity) var_of(b))) n_psi++;
2287 
2288  return(n_psi);
2289 }
2290 ␌
2291 /*********************************************************************************/
2292 /* RHO ENTITIES */
2293 /*********************************************************************************/
2294 
2295 /* entity make_rho_entity(int n)
2296  * input : an integer n giving the range of the RHO entity.
2297  * output : the entity PHI_n.
2298  * modifies : rho[] (eventually).
2299  * comment : finds or generates an entity representing a region descriptor
2300  * of indice n.
2301  * A region descriptor representes the value domain of one dimension
2302  * of an array, this dimension is represented by the indice.
2303  * Fortran accepts a maximum of 7 dimensions.
2304  *
2305  * Once a region descriptor is created, it is stored into a static array
2306  * (rho[]); thus, each next time a region descriptor entity is needed,
2307  * it is just picked up in rho[].
2308  * If the region descriptor is not in rho[], it may be in the table
2309  * where all entities are stored, because of previous computations.
2310  * At last, if it is not found there, it is created.
2311  */
2312 entity make_rho_entity(int n)
2313 {
2314  pips_assert("psy index between 1 and NB_MAX_ARRAY_DIM\n", 1<=n && n<=NB_MAX_ARRAY_DIM);
2315 
2316  /* rho indices are between 1 to NB_MAX_ARRAY_DIM. Array indices are between 0 to NB_MAX_ARRAY_DIM-1. */
2317  if (rho[n-1] == entity_undefined)
2318  {
2319  entity v;
2320  char rho_name[6];
2321  char * s;
2322 
2323  pips_assert ("n can't be more than a two digit number", n < 100);
2324  pips_assert ("RHO_PREFIX lenght has been changed", strlen (RHO_PREFIX) == 3);
2325 
2326  (void) strcpy(rho_name, RHO_PREFIX);
2327  (void) sprintf(rho_name+3,"%d",n);
2329  MODULE_SEP_STRING, rho_name, (char *) NULL));
2330 
2332  {
2333  v = make_entity(s,
2336  value_undefined);
2337  }
2338 
2339  rho[n-1] = v;
2340  }
2341  return (rho[n-1]);
2342 }
2343 
2344 
2345 list rho_entities_list(int rho_min, int rho_max)
2346 {
2347  list l_rho = NIL;
2348  int i;
2349 
2350  for(i=rho_min; i<=rho_max; i++)
2351  l_rho = gen_nconc(l_rho, CONS(ENTITY, make_rho_entity(i), NIL));
2352 
2353  return(l_rho);
2354 }
2355 
2357 {
2358  list l = reference_indices(ref);
2359 
2360  for (;!ENDP(l); POP(l))
2361  {
2365  (EXPRESSION(CAR(l)))));
2366  if (!entity_field_p(e))
2367  {
2368  if (variable_rho_p(e))
2369  return true;
2370  else
2371  return false;
2372  }
2373  }
2374  return true; /* in case of a scalar */
2375 }
2376 
2377 /* bool psi_region_p(effect reg)
2378  * input : a region.
2379  * output : true if it is a PSI region
2380  * modifies : nothing
2381  * comment : tests if the first indice of the reference is a PSI variable.
2382  */
2383 bool rho_region_p(region reg)
2384 {
2385  pips_assert("array region (not scalar)\n", !region_scalar_p(reg));
2386 
2387  return (rho_reference_p(effect_any_reference(reg)));
2388 }
2389 
2390 /* expression make_rho_expression(int n)
2391  * input : the range of the PHI entity to create.
2392  * output : an expression made of a PHI variable of range n;
2393  * modifies : nothing.
2394  */
2396 {
2400 }
2401 
2402 
2403 /* int base_nb_rho(Pbase b)
2404  * input : a base
2405  * output : the number of rho variables in this base.
2406  * modifies : nothing.
2407  * comment :
2408  */
2409 int base_nb_rho(Pbase b)
2410 {
2411  int n_rho = 0;
2412 
2413  for(; !VECTEUR_NUL_P(b); b = b->succ)
2414  if (variable_rho_p((entity) var_of(b))) n_rho++;
2415 
2416  return(n_rho);
2417 }
2418 ␌
2419 /*********************************************************************************/
2420 /* PHI AND PSY ENTITIES */
2421 /*********************************************************************************/
2422 
2424 {
2425 
2426  list l_ent = NIL;
2428  return NIL;
2429 
2430  if (psi_reference_p(ref))
2431  l_ent = psi_entities_list(1, (int) gen_length(reference_indices(ref)));
2432  else if (rho_reference_p(ref))
2433  l_ent = rho_entities_list(1, (int) gen_length(reference_indices(ref)));
2434  else
2435  l_ent = phi_entities_list(1, (int) gen_length(reference_indices(ref)));
2436 
2437  return(sc_entities_cfc_variables(sc, l_ent));
2438 
2439 }
2440 
2441 /* list region_phi_cfc_variables(effect reg)
2442  * input : a region
2443  * output : the list of variables that define the PHI or PSI variables, directly
2444  * or indirectly
2445  * modifies : nothing
2446  * comment : "cfc" stands for "Composante Fortement Connexe"; because
2447  * if systems are considered as graphs which vertices are
2448  * the constraints and which edges connect constraints
2449  * concerning at least one common variable, then this
2450  * function searches for the variables contained in
2451  * the strongly connected component that also contains
2452  * the PHI or PSI variables.
2453  */
2455 {
2456  if (region_scalar_p(reg))
2457  return(NIL);
2458  else
2460 }
2461 
2462 /* void psi_to_phi_region(effect reg)
2463  * input : a PSI region
2464  * output : the same region, using PHI variables.
2465  * modifies : reg
2466  * comment : also changes the reference.
2467  */
2468 void psi_to_phi_region(region reg)
2469 {
2470  int i, ndims = (int) gen_length(reference_indices(region_any_reference(reg)));
2471  reference reg_ref;
2472 
2473  /* if not a scalar region */
2474  if (ndims != 0)
2475  {
2476  Psysteme ps = region_system(reg);;
2477  for(i = 1; i<= ndims; i++)
2479  (Variable) make_phi_entity(i));
2480  }
2481 
2482  reg_ref = make_regions_reference(region_entity(reg));
2483 
2485 
2486  pips_assert("region cell must be a reference\n",
2488  cell_reference(effect_cell(reg)) = reg_ref;
2489 }
2490 
2491 /* void phi_to_psi_region(effect reg)
2492  * input : a PHI region
2493  * output : the same region, using PSI variables.
2494  * modifies : reg
2495  * comment : also changes the reference.
2496  */
2497 void phi_to_psi_region(region reg)
2498 {
2499  int i, ndims = (int) gen_length(reference_indices(region_any_reference(reg)));
2500  reference reg_ref;
2501 
2502  /* if not a scalar region */
2503  if (ndims != 0)
2504  {
2505  Psysteme ps = region_system(reg);;
2506  for(i = 1; i<= ndims; i++)
2508  (Variable) make_psi_entity(i));
2509  }
2510  reg_ref = make_regions_psi_reference(region_entity(reg));
2512  pips_assert("region cell must be a reference\n",
2514  cell_reference(effect_cell(reg)) = reg_ref;
2515 }
2516 
2517 
2519 {
2520 
2521  list l = reference_indices(ref);
2522 
2523  for (;!ENDP(l); POP(l))
2524  {
2528  (EXPRESSION(CAR(l)))));
2529  if (!entity_field_p(e))
2530  {
2531  if (variable_psi_p(e))
2532  return true;
2533  else
2534  return false;
2535  }
2536  }
2537  return true; /* in case of a scalar */
2538 }
2539 
2540 /* bool psi_region_p(effect reg)
2541  * input : a region.
2542  * output : true if it is a PSI region
2543  * modifies : nothing
2544  * comment : tests if the first indice of the reference is a PSI variable.
2545  */
2546 bool psi_region_p(region reg)
2547 {
2548  pips_assert("array region (not scalar)\n", !region_scalar_p(reg));
2549 
2550  return (psi_reference_p(effect_any_reference(reg)));
2551 }
2552 ␌
2553 /************************************************************* PROPERTIES */
2554 
2555 static bool exact_regions_property = false;
2556 static bool must_regions_property = false;
2557 static bool array_bounds_property = false;
2558 static bool disjunct_property = false;
2559 static bool op_statistics_property = false;
2560 
2561 bool exact_regions_p()
2562 {
2563  return exact_regions_property;
2564 }
2565 
2566 bool must_regions_p()
2567 {
2568  return must_regions_property;
2569 }
2570 
2571 bool array_bounds_p()
2572 {
2573  return array_bounds_property;
2574 }
2575 
2576 bool disjunct_regions_p()
2577 {
2578  return disjunct_property;
2579 }
2580 
2581 bool op_statistics_p()
2582 {
2583  return op_statistics_property;
2584 }
2585 
2586 void reset_op_statistics()
2587 {
2588  /* reset_proj_op_statistics(); */
2589  /* reset_binary_op_statistics(); */
2590 }
2591 
2593 {
2594  exact_regions_property = get_bool_property("EXACT_REGIONS");
2595  must_regions_property = get_bool_property("MUST_REGIONS");
2596  array_bounds_property = get_bool_property("REGIONS_WITH_ARRAY_BOUNDS");
2597  disjunct_property = get_bool_property("DISJUNCT_REGIONS");
2598  op_statistics_property = get_bool_property("REGIONS_OP_STATISTICS");
2599  if (op_statistics_property) reset_op_statistics();
2600 }
2601 
2603 {
2604  exact_regions_property = true;
2605  must_regions_property = true;
2606  array_bounds_property = get_bool_property("REGIONS_WITH_ARRAY_BOUNDS");
2607  disjunct_property = get_bool_property("DISJUNCT_IN_OUT_REGIONS");
2608  op_statistics_property = get_bool_property("REGIONS_OP_STATISTICS");
2609  if (op_statistics_property) reset_op_statistics();
2610 }
2611 
2612 ␌
2613 /********************************** COMPARISON FUNCTIONS FOR QSORT, AND SORT */
2614 
2615 static Pbase base_for_compare = BASE_NULLE;
2616 static Pbase no_phi_base_for_compare = BASE_NULLE;
2617 
2618 static void set_bases_for_compare(Pbase sorted_base)
2619 {
2620  Pbase b = sorted_base;
2621  base_for_compare = sorted_base;
2622 
2623  for(;!BASE_NULLE_P(b) && variable_phi_p((entity) var_of(b)); b = b->succ);
2624 
2625  no_phi_base_for_compare = b;
2626 }
2627 
2628 static void reset_bases_for_compare()
2629 {
2630  base_for_compare = BASE_NULLE;
2631  no_phi_base_for_compare = BASE_NULLE;
2632 }
2633 
2634 static int compare_region_constraints(Pcontrainte *pc1, Pcontrainte *pc2,
2635  bool equality_p);
2636 static int compare_region_vectors(Pvecteur *pv1, Pvecteur *pv2);
2637 static int compare_region_entities(entity *pe1, entity *pe2);
2638 
2639 static int compare_region_equalities(Pcontrainte *pc1, Pcontrainte *pc2)
2640 {
2641  return compare_region_constraints(pc1, pc2, true);
2642 }
2643 
2644 static int compare_region_inequalities(Pcontrainte *pc1, Pcontrainte *pc2)
2645 {
2646  return compare_region_constraints(pc1, pc2, false);
2647 }
2648 
2649 
2650 /* void region_sc_sort(Psysteme sc, Pbase sorted_base)
2651  * input : the predicate of a region, a base giving the priority order
2652  * of the variables (phi variables first).
2653  * output : nothing.
2654  * modifies : sc
2655  * comment : sorts each constraint of sc using compare_regions_vectors, and
2656  * sorts the constraints between them.
2657  */
2658 void region_sc_sort(Psysteme sc, Pbase sorted_base)
2659 {
2660  debug_on("REGIONS_PRETTYPRINT_DEBUG_LEVEL");
2661  ifdebug(1)
2662  {
2663  pips_debug(1, "\nbefore sort:\n");
2664  sc_syst_debug(sc);
2665  }
2666  sc_vect_sort(sc, compare_region_vectors);
2667  ifdebug(1)
2668  {
2669  pips_debug(1, "\nafter sc_vect_sort:\n");
2670  sc_syst_debug(sc);
2671  }
2672  sc->inegalites = region_constraints_sort(sc->inegalites, sorted_base, false);
2673  ifdebug(1)
2674  {
2675  pips_debug(1, "\nafter inequality sort:\n");
2676  sc_syst_debug(sc);
2677  }
2678  sc->egalites = region_constraints_sort(sc->egalites, sorted_base, true);
2679  ifdebug(1)
2680  {
2681  pips_debug(1, "\nafter sort:\n");
2682  sc_syst_debug(sc);
2683  }
2684  debug_off();
2685 }
2686 
2687 
2688 /* Pcontrainte region_constraints_sort(Pcontrainte c, Pbase sorted_base)
2689  * input : a region list of contraints, a base giving the priority order
2690  * of the variables (phi variables first).
2691  * output : the sorted list of constraints.
2692  * modifies : c.
2693  * comment : sorts the constraints using compare_region_constraints.
2694  */
2697  Pcontrainte c,
2698  Pbase sorted_base,
2699  bool equality_p)
2700 {
2701  set_bases_for_compare(sorted_base);
2703  // (c, BASE_NULLE, equality_p?
2704  (c, sorted_base, equality_p?
2705  ((int (*)()) compare_region_equalities):
2706  ((int (*)()) compare_region_inequalities), NULL);
2707  reset_bases_for_compare();
2708  return c;
2709 }
2710 
2711 
2712 /* Pbase region_sorted_base_dup(effect reg)
2713  * input : a region
2714  * output : a sorted copy of the base of its predicate.
2715  * modifies : nothing.
2716  * comment : sorts the base using compare_regions_vectors.
2717  */
2719 {
2720  Pbase sbase = base_dup(sc_base(region_system(reg)));
2721  vect_sort_in_place( &sbase, compare_region_vectors);
2722  return sbase;
2723 }
2724 
2725 
2726 /* static int compare_region_constraints(Pcontrainte *pc1, *pc2)
2727  * input : two constraints from a reigon predicate.
2728  * output : an integer for qsort: <0 if c1 must come first, >0 if c2 must come
2729  * first, 0 if the two constraints are equivalent.
2730  * modifies : nothing
2731  * comment : The criterium for the sorting is based first on the number of phi
2732  * variables in the constraints, second, on the order between variables
2733  * given by two static variables that must be initialized first.
2734  * (see a few screens before).
2735  */
2736 static int compare_region_constraints(Pcontrainte *pc1, Pcontrainte *pc2,
2737  bool equality_p)
2738 {
2739  Pvecteur
2740  v1 = (*pc1)->vecteur,
2741  v2 = (*pc2)->vecteur;
2742 
2743  int nb_phi_1 = base_nb_phi((Pbase) v1),
2744  nb_phi_2 = base_nb_phi((Pbase) v2);
2745 
2746  Pbase b = BASE_NULLE;
2747  Value val_1, val_2;
2748 
2749  /* not the same number of phi variables */
2750  if (nb_phi_1 != nb_phi_2)
2751  {
2752  /* one has no phi variables */
2753  if ((nb_phi_1 == 0) || (nb_phi_2 == 0))
2754  return( (nb_phi_1 ==0)? +1 : -1 );
2755  /* both have phi variables */
2756  else
2757  return( (nb_phi_1 > nb_phi_2)? +1 : -1);
2758  }
2759 
2760  if (nb_phi_1 == 0)
2761  /* both have no phi variables : the comparison basis only
2762  consists of variables other than phi variables */
2763  b = no_phi_base_for_compare;
2764  else
2765  {
2766  /* particular treatment for phi variables */
2767  b = base_for_compare;
2768  for(; b!= no_phi_base_for_compare; b = b->succ)
2769  {
2770  val_1 = vect_coeff(var_of(b), v1);
2771  val_2 = vect_coeff(var_of(b), v2);
2772  if (value_ne(val_1,val_2)) {
2773  if (value_zero_p(val_1))
2774  return(1);
2775  if (value_zero_p(val_2))
2776  return(-1);
2777  return VALUE_TO_INT(value_minus(val_1,val_2));
2778  }
2779  }
2780  }
2781 
2782 
2783  if(equality_p)
2784  {
2785  int passe;
2786  Pvecteur coord, v;
2787 
2788  for(passe = 1; passe <= 2; passe++)
2789  {
2790  int positive_terms = 0, negative_terms = 0;
2791 
2792  v = (passe == 1) ? v1 : v2;
2793  for(coord = v; !VECTEUR_NUL_P(coord); coord = coord->succ)
2794  {
2795  if(vecteur_var(coord)!= TCST)
2796  {
2797  if(value_pos_p(vecteur_val(coord) ))
2798  positive_terms++;
2799  else
2800  negative_terms++;
2801  }
2802  }
2803 
2804  if(negative_terms > positive_terms)
2805  vect_chg_sgn(v);
2806  else
2807  if(negative_terms == positive_terms)
2808  /* entities are already sorted in v */
2809  if ((vecteur_var(v) != TCST) &&
2811  vect_chg_sgn(v);
2812  }
2813  }
2814 
2815  /* variables other than phis are handled */
2816  for(; !BASE_NULLE_P(b); b = b->succ) {
2817  val_1 = vect_coeff(var_of(b), v1);
2818  val_2 = vect_coeff(var_of(b), v2);
2819  if (value_ne(val_1,val_2))
2820  {
2821  if (value_zero_p(val_1))
2822  return(1);
2823  if (value_zero_p(val_2))
2824  return(-1);
2825  return VALUE_TO_INT(value_minus(val_1,val_2));
2826  }
2827  }
2828 
2829  val_1 = vect_coeff(TCST, v1);
2830  val_2 = vect_coeff(TCST, v2);
2831 
2832  if (value_ne(val_1,val_2))
2833  {
2834  if (value_zero_p(val_1))
2835  return(1);
2836  if (value_zero_p(val_2))
2837  return(-1);
2838  return VALUE_TO_INT(value_minus(val_1,val_2));
2839  }
2840 
2841  return(0);
2842 }
2843 
2844 
2845 /* static int compare_region_vectors(Pvecteur *pv1, *pv2)
2846  * input : two vectors from a region predicate
2847  * output : an integer for qsort
2848  * modifies : nothing
2849  * comment : phi variables come first, the other variables are alphabetically sorted.
2850  */
2851 static int compare_region_vectors(Pvecteur *pv1, Pvecteur *pv2)
2852 {
2853  return(compare_region_entities((entity*)&var_of(*pv1),
2854  (entity*)&var_of(*pv2)));
2855 }
2856 
2857 
2858 /* static int compare_region_entities(entity *pe1, *pe2)
2859  * input : two entities
2860  * output : a integer for qsort
2861  * modifies : nothing
2862  * comment : phi variables come first, the other variables are alphabetically sorted.
2863  */
2864 static int compare_region_entities(entity *pe1, entity *pe2)
2865 {
2866  int phi_1 = false, phi_2 = false,
2867  null_1 = (*pe1==(entity)NULL),
2868  null_2 = (*pe2==(entity)NULL);
2869 
2870  if (null_1 && null_2)
2871  return(0);
2872 
2873  if (!null_1) phi_1 = variable_phi_p(*pe1);
2874  if (!null_2) phi_2 = variable_phi_p(*pe2);
2875 
2876  if (null_1 && phi_2)
2877  return(1);
2878 
2879  if (null_2 && phi_1)
2880  return (-1);
2881 
2882  if (null_1 || null_2)
2883  return(null_2-null_1);
2884 
2885  /* if both entities are phi variables, or neither one */
2886  if (phi_1 - phi_2 == 0) {
2887  /* FI: This does not work well with C scope system */
2888  //return(strcmp(entity_name(*pe1), entity_name(*pe2)));
2889  string s1 = entity_name_without_scope(*pe1);
2890  string s2 = entity_name_without_scope(*pe2);
2891  int result = strcmp(s1,s2);
2892 
2893  free(s1);
2894  free(s2);
2895  return result;
2896  }
2897  /* if one and only one of the entities is a phi variable */
2898  else
2899  return(phi_2 - phi_1);
2900 }
2901 ␌
2902 /********************************** MANIPULATION OF ENTITIES AND VARIABLES */
2903 
2904 
2906 {
2907  Psysteme sc = sc_new();
2909  int dim;
2910 
2911  for (dim = 1; !ENDP(ldim); dim++, ldim = CDR(ldim))
2912  {
2913  expression dl, du;
2914 
2915  dl = dimension_lower(DIMENSION(CAR(ldim)));
2916  ifdebug(8) {
2917  pips_debug(8,
2918  "addition of inequality :\n%s - PHI%d <= 0\n",
2919  expression_to_string(dl), dim);
2920  }
2921  (void) sc_add_phi_equation(&sc, dl, dim, NOT_EG, NOT_PHI_FIRST);
2922 
2923  du = dimension_upper(DIMENSION(CAR(ldim)));
2924  ifdebug(8) {
2925  pips_debug(8,
2926  "addition of inequality :\nPHI%d - %s <= 0\n",
2927  dim, expression_to_string(du));
2928  }
2929  (void) sc_add_phi_equation(&sc, du, dim, NOT_EG, PHI_FIRST);
2930 
2931  } /* for */
2932  return(sc);
2933 }
2934 
2935 /* list variables_to_int_variables(list l_var)
2936  * input : a list of variables
2937  * output : a list containing the intermediate variables corresponding to
2938  * initial variables, in the same order.
2939  * modifies : nothing.
2940  * comment :
2941  */
2943 {
2944  list l_int = NIL;
2945 
2946  MAP(ENTITY, e,
2947  {
2949  list l_tmp = CONS(ENTITY, e_int, NIL);
2950  l_int = gen_nconc(l_int, l_tmp);/* to be in the same order as l_var */
2951  debug(8, "", "%s -> %s\n",
2952  (e == (entity) TCST) ? "TCST" : pips_user_value_name(e),
2953  (e_int == (entity) TCST) ? "TCST" : pips_user_value_name(e_int));
2954  },
2955  l_var);
2956 
2957  return(l_int);
2958 }
2959 
2960 
2961 /* list variables_to_old_variables(list l_var)
2962  * input : a list of variables
2963  * output : a list containing the old variables corresponding to
2964  * initial variables, in the same order.
2965  * modifies : nothing.
2966  * comment :
2967  */
2969 {
2970  list l_old = NIL;
2971 
2972  FOREACH(ENTITY, e, l_var)
2973  {
2974  entity e_old = entity_to_old_value(e);
2975  list l_tmp = CONS(ENTITY, e_old, NIL);
2976  l_old = gen_nconc(l_old, l_tmp); /* to be in the same order as l_var */
2977  debug(8, "", "%s -> %s\n",
2978  (e == (entity) TCST) ? "TCST" : pips_user_value_name(e),
2979  (e_old == (entity) TCST) ? "TCST" : pips_user_value_name(e_old));
2980  }
2981 
2982  return(l_old);
2983 }
2984 
2985 
2986 
2987 /* Psysteme sc_list_variables_rename(Psysteme sc, list l_var, l_var_new)
2988  * input : a system of constraints, a list of variables to be renamed,
2989  * and the list of the new names.
2990  * output : the system in which the variables are renamed.
2991  * modifies : the initial system.
2992  * comment :
2993  */
2994 Psysteme sc_list_variables_rename(Psysteme sc, list l_var, list l_var_new)
2995 {
2996  list ll_var_new = l_var_new;
2997 
2998  MAP(ENTITY, e,
2999  {
3000  entity e_new = ENTITY(CAR(ll_var_new));
3001  sc = sc_variable_rename(sc, (Variable) e, (Variable) e_new);
3002  ll_var_new = CDR(ll_var_new);
3003  },
3004  l_var);
3005 
3006  return(sc);
3007 }
3008 
3009 
3010 
3011 /* list function_formal_parameters(entity func)
3012  * input : an entity representing a function.
3013  * output : the unsorted list (of entities) of parameters of the function "func".
3014  * modifies : nothing.
3015  * comment : Made from "entity_to_formal_integer_parameters()" that considers
3016  * only integer variables.
3017  */
3019 {
3020  list formals = NIL;
3021  list decl = list_undefined;
3022 
3023  pips_assert("func must be a function",entity_module_p(func));
3024 
3025  decl = code_declarations(entity_code(func));
3026  MAP(ENTITY, e,
3027  {
3029  formals = CONS(ENTITY, e, formals);
3030  },
3031  decl);
3032 
3033  return (formals);
3034 }
3035 
3036 
3037 /* char *func_entity_name(entity e)
3038  * input : an entity representing a function.
3039  * output : the name of the function represented by the entity given in argument.
3040  * modifies : nothing.
3041  */
3042 char *func_entity_name(entity e)
3043 {
3044  return((e == entity_undefined) ? "TCST" : entity_name(e));
3045 }
3046 
3047 
3048 
3049 
3050 /* bool same_common_variables_p(entity e1, e2)
3051  * output : returns true if both entities, which are common variables,
3052  * occupy the same place in a COMMON, and, also, have
3053  * the same shape.
3054  * modifies : nothing .
3055  * comment :
3056  * Four comparisons have to be made :
3057  * 1. offset in the COMMON
3058  * 2. Fortran type
3059  * 3. number of dimensions
3060  * 4. dimensions size (in case of arrays)
3061  *
3062  * Note : this function is used with common variables of the same
3063  * COMMON in two different subroutines.
3064  */
3066 {
3067  bool equal = false;
3068  storage st1, st2;
3069  int offs1, offs2;
3070 
3071  ifdebug(5) {
3072  pips_debug(5, "entities %s and %s\n", entity_name(e1),entity_name(e2));
3073  }
3074 
3075  st1 = entity_storage(e1);
3076  st2 = entity_storage(e2);
3077  if ((! (storage_tag(st1) == is_storage_ram)) ||
3078  (! (storage_tag(st2) == is_storage_ram))) {
3079  user_error("same_common_array_p", "not COMMON entities : %s or %s",
3080  entity_name(e1), entity_name(e2));
3081  }
3082 
3083  offs1 = ram_offset(storage_ram(st1));
3084  offs2 = ram_offset(storage_ram(st2));
3085 
3086  /* Same offset in the COMMON */
3087  if (offs1 == offs2) {
3088  type ty1, ty2;
3089  basic basic1, basic2;
3090 
3091  ty1 = entity_type(e1);
3092  ty2 = entity_type(e2);
3093  if ((! (type_tag(ty1) == is_type_variable)) ||
3094  (! (type_tag(ty2) == is_type_variable))) {
3095  pips_internal_error("arrays entities with not variable type : %s %s",
3096  entity_name(e1), entity_name(e2));
3097  }
3098 
3099  basic1 = variable_basic(type_variable(ty1));
3100  basic2 = variable_basic(type_variable(ty2));
3101 
3102  /* Same fortran type. */
3103  if (SizeOfElements(basic1) == SizeOfElements(basic2)) {
3104  int nb_dims1 = NumberOfDimension(e1);
3105  int nb_dims2 = NumberOfDimension(e2);
3106 
3107  /* Same number of dimensions. */
3108  if (nb_dims1 == nb_dims2) {
3109  int count_dim;
3110  for (count_dim = 1, equal = true;
3111  (count_dim <= nb_dims1) && (equal); count_dim++) {
3112  int size1 = SizeOfIthDimension(e1, count_dim);
3113  int size2 = SizeOfIthDimension(e2, count_dim);
3114 
3115  /* Same dimension size. */
3116  if (size1 != size2) {
3117  equal = false;
3118  }
3119  }
3120  }
3121  }
3122  }
3123  return(equal);
3124 }
3125 
3126 ␌
3127 /*************************** MANIPULATION OF PRECONDITIONS AND TRANSFORMERS */
3128 
3129 
3130 /* Psysteme sc_loop_proper_precondition(loop l)
3131  * input : a loop
3132  * output : a Psysteme representing the proper precondition of the loop,
3133  * e.g. the constraints induced by the loop range.
3134  * modifies : nothing.
3135  * comment : should not be there !
3136  */
3138 {
3139  entity i = loop_index(l);
3140  Psysteme sc;
3141  transformer loop_prec;
3142  transformer loop_body_trans = load_statement_transformer(loop_body(l));
3143 
3144  loop_prec = make_transformer(NIL,
3146  vect_new((Variable) i, VALUE_ONE))));
3147  loop_prec =
3148  add_index_range_conditions(loop_prec,
3149  i,
3150  loop_range(l),
3151  loop_body_trans);
3152 
3153  sc = predicate_system(transformer_relation(loop_prec));
3155  newgen_Psysteme(SC_UNDEFINED);
3156  free_transformer(loop_prec);
3157 
3158  return sc;
3159 }
3160 ␌
3161 /******************************************************************** MISC */
3162 
3163 /* is the context empty?
3164  */
3166 {
3167  Psysteme sc_context;
3168 
3170  {
3171  /* this happens to the CONTINUE statement of the exit node
3172  * even if unreachable. Thus transformer are not computed,
3173  * orderings are not set... however gen_multi_recurse goes there.
3174  * I just store NIL, what seems reasonnable an answer.
3175  * It seems to be sufficient for other passes.
3176  * I should check that it is indeed the exit node?
3177  * FC (RK).
3178  */
3179  pips_debug(3, "undefined contexted found, returned as empty\n");
3180  return true;
3181  }
3182  /* else
3183  */
3184 
3186  return sc_empty_p(sc_context);
3187 }
3188 
3189 string region_to_string(effect reg __attribute__ ((unused)))
3190 {
3191  return strdup("[region_to_string] no longer implemented\n");
3192 }
3193 
3194 static bool max_one_phi_var_per_constraint(c)
3195 Pcontrainte c;
3196 {
3197  for(; c; c=c->succ)
3198  if (base_nb_phi(c->vecteur)>=2) return false;
3199 
3200  return true;
3201 }
3202 
3203 /* returns true is syst defines a rectangle on phi variables
3204  */
3206 {
3207 
3208  Psysteme syst = region_system(r);
3209  /* this is an approximation, and the system should be normalized
3210  * for the result to be correct, I guess...
3211  */
3212  return max_one_phi_var_per_constraint(sc_egalites(syst)) &&
3213  max_one_phi_var_per_constraint(sc_inegalites(syst));
3214 }
3215 
3216 bool rectangular_must_region_p(var, s)
3217 entity var;
3218 statement s;
3219 {
3221 
3222  FOREACH(EFFECT, e,le)
3223  {
3225  {
3228  {
3229  pips_debug(6, "FALSE\n"); return false;
3230  }
3231  }
3232  }
3233  pips_debug(6, "TRUE\n");
3234  return true;
3235 }
3236 
3237 /********************************************************************
3238  * SG awful contributions to BC wonderful work
3239  */
3240 
3241 
3242 /* return true if an expression is a field access or a constant phi with regard to sc */
3243 static bool expression_is_a_constant_reference_p(expression exp, Psysteme sc) {
3244  if(expression_reference_p(exp)) { // a phi or a field ?
3246  entity var = reference_variable(ref);
3247  if(entity_field_p(var)) return true;
3248  else if(variable_phi_p(var)) { // we should stop there, unless we have a constant index
3249  /* iterate over the region equalities to find this particular phi variable */
3250  Psysteme scd = sc_dup(sc);
3252  Pcontrainte lower,upper;
3254  &sc_inegalites(scd), &lower, &upper);
3255  bool constant_index_p =
3256  (!CONTRAINTE_UNDEFINED_P(upper) && !CONTRAINTE_UNDEFINED_P(lower) && bounds_equal_p(var,lower,upper)) ;
3257  sc_free(scd);
3258  if(constant_index_p) {
3259  return true;
3260  }
3261  }
3262  }
3263  return false;
3264 }
3265 /* computes the rectangular hull of a region
3266  * if the region indices contain fields and @p nofield is set to true
3267  * they are removed to ensure a non strided access
3268  * that is if the field is at the head, it is kept (struct of array)
3269  * if it is in the tail, it is ignored
3270  * if it is in the middle, we are in great trouble
3271  * and perform an over-approximation of ignoring all remaining accesses
3272  *
3273  */
3274 region region_rectangular_hull(region reg, bool nofield)
3275 {
3276  region hyper = copy_effect(reg);
3277  if(nofield) {
3278  /* this is the stride fix */
3279  list iter = reference_indices(region_any_reference(hyper)),prev;
3280  prev=iter;
3281 
3282  bool constant_path_head_p = true;
3283  while(!ENDP(iter) && constant_path_head_p ) {
3284  /* head : keep everything that does not introduce a stride */
3285  for(;!ENDP(iter);POP(iter)) {
3286  expression e = EXPRESSION(CAR(iter));
3287  if(expression_reference_p(e) &&
3289  break; // stop as soon has we meet a field
3290  }
3291  constant_path_head_p &= expression_is_a_constant_reference_p(e, region_system(reg));
3292  prev=iter;
3293  }
3294  /* body keep all fields indices if we have a constant path head*/
3295  if(constant_path_head_p) {
3296  for(;!ENDP(iter);POP(iter)) {
3297  expression e = EXPRESSION(CAR(iter));
3298  prev=iter;
3299  if(!expression_reference_p(e) ||
3301  constant_path_head_p &= expression_is_a_constant_reference_p(e, region_system(reg));
3302  break; // eats up all fields
3303  }
3304  }
3305  }
3306  }
3307  /* tail : once a field is met , we cannot go on unless we have a constant path head */
3308  list tail = NIL;
3309  if(!ENDP(prev)) { tail = CDR(prev) ; CDR(prev)=NIL; }
3310  /* if we cut the tail , approximation is may */
3311  if(!ENDP(tail)) {
3313  list phis = NIL;
3314  FOREACH(EXPRESSION,exp,tail) {
3315  if(expression_reference_p(exp) ) {
3317  if(variable_phi_p(var)) phis = CONS(ENTITY,var,phis);
3318  }
3319  }
3320  phis=gen_nreverse(phis);
3322  gen_free_list(phis);
3323  }
3324  gen_full_free_list(tail);
3325  }
3326 
3327  /* the real rectangular hull begins now */
3328 
3329  /* first gather all phis */
3330  list phis = NIL;
3335  phis=gen_nreverse(phis);
3336 
3337  /* then for each of the phis, generate a list of all other phis
3338  * and project the system along this variables */
3339  region nr = effect_undefined;
3340  FOREACH(ENTITY, phi_i, phis) {
3341  list other_phis = gen_copy_seq(phis);
3342  gen_remove_once(&other_phis,phi_i);
3343  region partial = copy_effect(hyper);
3344  region_exact_projection_along_parameters(partial,other_phis);
3345  if(effect_undefined_p(nr)) nr=partial;
3346  else {
3347  region_sc_append(nr,region_system(partial),1);
3348  free_effect(partial);
3349  }
3350  gen_free_list(other_phis);
3351  }
3352  gen_free_list(phis);
3353  if(!effect_undefined_p(nr)) {
3354  sc_fix(region_system(nr));
3355  region_system(hyper)=sc_dup(region_system(nr));
3356  if(!sc_equal_p(region_system(hyper),region_system(reg)))
3358  free_effect(nr);
3359  }
3360  // in case of error, we keep the original region
3361  return hyper;
3362 }
3363 
3364 /* translates a reference form a region into a valid expression
3365  * it handles fields accesses conversion, but does not changes phi variables
3366  * it is up to the user to use replace_entity on the generated expression according to its needs
3367  * no sharing introduced between returned expression and @p r
3368  */
3372  );
3374  if(expression_reference_p(index) &&
3376  p = MakeBinaryCall(
3378  p,
3379  copy_expression(index)
3380  );
3381  }
3382  else {
3383  if(expression_reference_p(p)) {
3385  reference_indices(pr)=
3388  );
3389  }
3390  else if(expression_subscript_p(p)) {
3392  subscript_indices(ps)=
3395  );
3396  }
3397  else {
3398  pips_assert("is a field",expression_field_p(p));
3402  p,
3404  )
3405  )
3406  );
3407  }
3408 
3409  }
3410  }
3411  return p;
3412 }
3413 
3414 /* computes the volume of a region
3415  * output it as a Polynomial representing the number of elements counted
3416  */
3418 {
3420  if(rectangular_region_p(reg)) // in that case, use a simpler algorithm */
3421  {
3422  Psysteme r_sc = region_system(reg);
3423  sc_normalize2(r_sc);
3425  p = make_polynome(1.,TCST,0);
3426  for(list iter = reference_indices(ref);!ENDP(iter); POP(iter))
3427  {
3428  expression index = EXPRESSION(CAR(iter));
3429  Variable phi = expression_to_entity(index);
3430  if(variable_phi_p((entity)phi)) {
3431  /* first search into the equalities if any */
3432  bool found = false;
3433  for(Pcontrainte c = sc_egalites(r_sc);
3435  c=contrainte_succ(c)) {
3436  Pvecteur v = c->vecteur;
3437  if((found=base_contains_variable_p(v,phi))) {
3438  // if an equality is found, the volume is not affected
3439  break;
3440  }
3441  }
3442  if(!found) {
3443 
3444  /* else try to find the range */
3445  Psysteme sc = sc_dup(r_sc);
3447  Pcontrainte lower,upper;
3448  constraints_for_bounds(phi, &sc_inegalites(sc), &lower, &upper);
3449  if( !CONTRAINTE_UNDEFINED_P(lower) && !CONTRAINTE_UNDEFINED_P(upper))
3450  {
3451  /* this is a constant */
3452  if(bounds_equal_p(phi,lower,upper))
3453  ; /* skip */
3454  /* this is a range : eupper-elower +1 */
3455  else
3456  {
3459 
3460  expression diff = make_op_exp(MINUS_OPERATOR_NAME,eupper,elower);
3462  Ppolynome pdiff = expression_to_polynome(diff);
3463  free_expression(diff);
3464  p=polynome_mult(p,pdiff);
3465  }
3466  }
3467  else {
3468  pips_user_warning("failed to analyse region\n");
3469  }
3470  sc_free(sc);
3471  }
3472  }
3473  }
3474  }
3475  else {
3476  Psysteme r_sc = region_system(reg);
3477  sc_fix(r_sc);
3478  Pbase sorted_base = region_sorted_base_dup(reg);
3479  sc_base(r_sc)=sorted_base;
3480  Pbase local_base = BASE_NULLE;
3481  for(Pbase b = sc_base(r_sc);!BASE_NULLE_P(b);b=b->succ)
3482  if(!variable_phi_p((entity)b->var))
3483  local_base=base_add_variable(local_base,b->var);
3484 
3485  const char * base_names [sc_dimension(r_sc)];
3486  int i=0;
3487  for(Pbase b = local_base;!BASE_NULLE_P(b);b=b->succ)
3488  base_names[i++]=entity_user_name((entity)b->var);
3489 
3490  ifdebug(1) print_region(reg);
3491 
3492  p = sc_enumerate(r_sc,
3493  local_base,
3494  base_names);
3495  }
3496  return p;
3497 }
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
action copy_action(action p)
ACTION.
Definition: effects.c:77
void free_effect(effect p)
Definition: effects.c:451
bool effect_consistent_p(effect p)
Definition: effects.c:457
approximation make_approximation(enum approximation_utype tag, void *val)
Definition: effects.c:176
approximation make_approximation_may(void)
Definition: effects.c:179
effect copy_effect(effect p)
EFFECT.
Definition: effects.c:448
void free_transformer(transformer p)
Definition: ri.c:2616
transformer make_transformer(list a1, predicate a2)
Definition: ri.c:2649
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
subscript make_subscript(expression a1, list a2)
Definition: ri.c:2327
predicate make_predicate(Psysteme a1)
Definition: ri.c:1820
void free_reference(reference p)
Definition: ri.c:2050
storage make_storage(enum storage_utype tag, void *val)
Definition: ri.c:2273
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
syntax copy_syntax(syntax p)
SYNTAX.
Definition: ri.c:2442
void free_expression(expression p)
Definition: ri.c:853
void free_syntax(syntax p)
Definition: ri.c:2445
syntax make_syntax(enum syntax_utype tag, void *val)
Definition: ri.c:2491
syntax make_syntax_subscript(subscript _field_)
Definition: ri.c:2509
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
#define IS_EG
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
bool entity_abstract_location_p(entity al)
#define value_pos_p(val)
#define value_minus(v1, v2)
#define VALUE_TO_INT(val)
void const char const char const int
#define value_ne(v1, v2)
#define value_zero_p(val)
int Value
#define VALUE_ONE
#define value_neg_p(val)
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
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
Pbase vect_add_variable(Pbase b, Variable v)
package vecteur - routines sur les bases
Definition: base.c:61
bool transformer_equations_constrain_variable_p(const transformer t, const entity v)
Is value v used with a non-zero coefficient by the equations of transformer t?
Definition: basic.c:963
bool transformer_inequalities_constrain_variable_p(const transformer t, const entity v)
Is value v used with a non-zero coefficient by the inequalities of transformer t?
Definition: basic.c:972
transformer transformer_identity()
Allocate an identity transformer.
Definition: basic.c:110
void vect_debug(Pvecteur v)
constraint.c
Definition: constraint.c:43
void sc_syst_debug(Psysteme s)
constraint_to_text.c
#define CONTRAINTE_UNDEFINED_P(c)
#define contrainte_succ(c)
struct Scontrainte * Pcontrainte
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
void constraints_for_bounds(Variable, Pcontrainte *, Pcontrainte *, Pcontrainte *)
void constraints_for_bounds(var, pinit, plower, pupper) Variable var; Pcontrainte *pinit,...
Definition: unaires.c:176
expression constraints_to_loop_bound(Pcontrainte, Variable, bool, entity)
expression constraints_to_loop_bound(c, var, is_lower)
bool bounds_equal_p(Variable, Pcontrainte, Pcontrainte)
this function checks whether the lower and upper constraints are going to generate the same bound on ...
#define NB_MAX_ARRAY_DIM
#define region_any_reference(reg)
To be avoided.
#define region_action(reg)
#define debug_region_consistency(reg)
#define region_system_(reg)
#define region_entity(reg)
#define region_system(reg)
#define region_empty_p(reg)
#define region_approximation_tag(reg)
#define make_region(reference, action, approximation, system)
#define REGION
#define region
simulation of the type region
#define region_scalar_p(reg)
list all_regions_sc_append(list, Psysteme, bool)
bool rho_region_p(effect)
list function_formal_parameters(entity)
void convex_region_change_ith_dimension_expression(effect, expression, int)
list region_to_may_region_list(effect)
list region_add_to_regions(effect, list)
entity make_phi_entity(int)
void all_regions_variable_rename(list, entity, entity)
list regions_write_regions(list)
effect make_reference_region(reference, action)
Psysteme sc_list_variables_rename(Psysteme, list, list)
list regions_sc_append_and_normalize(list, Psysteme, bool, bool, int)
void region_value_substitute(effect, entity, entity)
void get_in_out_regions_properties(void)
bool exact_regions_p(void)
list regions_read_regions(list)
void regions_end(void)
bool must_regions_p(void)
bool empty_convex_context_p(transformer)
list rho_entities_list(int, int)
list variables_to_int_variables(list)
expression make_rho_expression(int)
Psysteme sc_loop_proper_precondition(loop)
void psi_to_phi_region(effect)
void region_free(effect)
expression make_psi_expression(int)
bool rho_reference_p(reference)
void regions_init(void)
bool disjunct_regions_p(void)
list region_to_list(effect)
list convex_effect_to_phi_entity_list(effect)
list phi_entities_list(int, int)
effect entity_whole_region(entity, action)
bool add_precondition_to_scalar_convex_regions
bool same_common_variables_p(entity, entity)
void region_sc_append_and_normalize(effect, Psysteme, int)
effect region_append(effect, effect)
list sc_entities_cfc_variables(Psysteme, list)
void convex_region_descriptor_remove_ith_dimension(effect, int)
reference make_pointed_regions_reference(entity, bool)
list region_to_store_independent_region_list(effect, bool)
bool array_bounds_p(void)
list region_phi_cfc_variables(effect)
Pcontrainte region_constraints_sort(Pcontrainte, Pbase, bool)
bool rectangular_must_region_p(entity, statement)
void phi_first_sort_base(Pbase *)
bool psi_region_p(effect)
int base_nb_phi(Pbase)
list beta_entities_list(int, int)
void get_regions_properties(void)
bool sc_add_phi_equation(Psysteme *, expression, int, bool, bool)
effect reference_whole_region(reference, action)
list cell_reference_phi_cfc_variables(reference, Psysteme)
void phi_to_psi_region(effect)
void region_sc_append(effect, Psysteme, bool)
expression make_phi_expression(int)
reference make_regions_psi_reference(entity)
list regions_dup(list)
list psi_entities_list(int, int)
list regions_to_write_regions(list)
Psysteme region_sc_normalize(Psysteme, int)
Ppolynome region_enumerate(effect)
Ppolynome sc_enumerate(Psysteme, Pbase, const char *[])
sc_enumerate.c
Definition: sc_enumerate.c:307
int base_nb_psi(Pbase)
list region_entities_cfc_variables(effect, list)
list regions_add_context(list, transformer)
int base_nb_rho(Pbase)
void region_exact_projection_along_variable(effect, entity)
entity make_beta_entity(int)
utils.c
effect region_dup(effect)
expression region_reference_to_expression(reference)
Psysteme entity_declaration_sc(entity)
Psysteme cell_system_sc_append_and_normalize(Psysteme, Psysteme, int)
void array_regions_variable_rename(list, entity, entity)
string region_to_string(effect)
bool rectangular_region_p(effect)
list scalar_regions_sc_append(list, Psysteme, bool)
void region_exact_projection_along_parameters(effect, list)
effect convex_effect_field_to_rank_conversion(effect)
bool psi_reference_p(reference)
Pbase region_sorted_base_dup(effect)
void convex_region_add_expression_dimension(effect, expression)
list regions_sc_append(list, Psysteme, bool, bool, bool)
bool op_statistics_p(void)
reference make_regions_reference(entity)
list regions_to_nil_list(effect, effect)
effect region_rectangular_hull(effect, bool)
void region_sc_sort(Psysteme, Pbase)
char * func_entity_name(entity)
entity make_psi_entity(int)
int phi_entity_rank(entity)
list regions_add_region(list, effect)
void regions_free(list)
void set_region_interprocedural_translation(void)
void reset_op_statistics(void)
entity make_rho_entity(int)
list array_regions_sc_append(list, Psysteme, bool)
list region_to_nil_list(effect)
void reset_region_interprocedural_translation(void)
list array_regions_sc_append_and_normalize(list, Psysteme, int)
list variables_to_old_variables(list)
list regions_remove_variables_regions(list, list)
bool effects_private_current_context_empty_p(void)
transformer effects_private_current_context_head(void)
bool effects_private_current_context_stack_initialized_p(void)
list load_statement_local_regions(statement)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define BETA_PREFIX
#define effect_approximation_tag(eff)
#define variable_rho_p(e)
#define variable_psi_p(e)
#define RHO_PREFIX
#define PHI_PREFIX
#define PSI_PREFIX
#define variable_phi_p(e)
true if e is a phi variable PHI entities have a name like: REGIONS:PHI#, where # is a number.
tag approximation_and(tag, tag)
tag approximation_and(tag t1, tag t2) input : two approximation tags.
Definition: effects.c:1198
action make_action_write_memory(void)
To ease the extension of action with action_kind.
Definition: effects.c:1011
bool store_effect_p(effect)
Definition: effects.c:1062
#define cell_reference(x)
Definition: effects.h:469
#define effect_undefined_p(x)
Definition: effects.h:615
#define cell_reference_p(x)
Definition: effects.h:467
#define approximation_exact_p(x)
Definition: effects.h:369
#define effect_undefined
Definition: effects.h:614
#define action_write_p(x)
Definition: effects.h:314
#define action_read_p(x)
Definition: effects.h:311
#define cell_tag(x)
Definition: effects.h:466
@ is_approximation_may
Definition: effects.h:341
@ is_approximation_exact
Definition: effects.h:343
#define effect_approximation(x)
Definition: effects.h:644
#define newgen_Psysteme(p)
Definition: effects.h:47
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#define effect_cell(x)
Definition: effects.h:640
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void gen_full_free_list(list l)
Definition: genClib.c:1023
if(!(yy_init))
Definition: genread_lex.c:1029
void free(void *)
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#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
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#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
void * gen_find_eq(const void *item, const list seq)
Definition: list.c:422
list gen_append(list l1, const list l2)
Definition: list.c:471
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
#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 user_error(fn,...)
Definition: misc-local.h:265
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
static entity rank
#define MODULE_SEP_STRING
Definition: naming-local.h:30
#define assert(ex)
Definition: newgen_assert.h:41
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
char * string
STRING.
Definition: newgen_types.h:39
#define UU
Definition: newgen_types.h:98
#define bool_undefined
Definition: newgen_types.h:84
Ppolynome make_polynome(float coeff, Variable var, Value expo)
Ppolynome make_polynome(float coeff, Variable var, Value expo) PRIVATE allocates space for,...
Definition: pnome-alloc.c:100
Ppolynome polynome_mult(Ppolynome pp1, Ppolynome pp2)
Ppolynome polynome_mult(Ppolynome pp1, Ppolynome pp2) returns pp1 * pp2.
Definition: pnome-bin.c:287
#define POLYNOME_UNDEFINED
string reference_to_string(reference r)
Definition: expression.c:87
string expression_to_string(expression e)
Definition: expression.c:77
#define print_region(x)
Definition: print.c:343
#define NOT_EG
Definition: propagate.c:41
#define NOT_PHI_FIRST
Definition: propagate.c:44
#define PHI_FIRST
Definition: propagate.c:43
#define MINUS_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define NORMALIZE_EXPRESSION(e)
#define ENTITY_PRE_DECREMENT_P(e)
#define make_entity(n, t, s, i)
#define ENTITY_POST_DECREMENT_P(e)
#define FIELD_OPERATOR_NAME
Definition: ri-util-local.h:91
#define ENTITY_POST_INCREMENT_P(e)
#define ENTITY_PRE_INCREMENT_P(e)
#define REGIONS_MODULE_NAME
Already defined.
#define DIVIDE_OPERATOR_NAME
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
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 dummy_parameter_entity_p(entity p)
is p a dummy parameter?
Definition: entity.c:1941
code entity_code(entity e)
Definition: entity.c:1098
string entity_name_without_scope(entity e)
allocates a new string
Definition: entity.c:543
bool entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857
void print_entities(list l)
Definition: entity.c:167
bool fortran_module_p(entity m)
Test if a module is in Fortran.
Definition: entity.c:2799
bool entity_module_p(entity e)
Definition: entity.c:683
entity CreateIntrinsic(string name)
this function does not create an intrinsic function because they must all be created beforehand by th...
Definition: entity.c:1311
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
int entity_field_rank(entity f)
f is a field of a structure or of an union: what is its rank?
Definition: entity.c:940
subscript expression_subscript(expression e)
Definition: expression.c:1843
expression reference_to_expression(reference r)
Definition: expression.c:196
range expression_range(expression e)
Definition: expression.c:1853
bool expression_field_p(expression e)
The expression is of kind "s.a", where "s" is a struct and a "a" field.
Definition: expression.c:491
bool expression_call_p(expression e)
Definition: expression.c:415
bool expression_subscript_p(expression e)
Definition: expression.c:1838
bool field_expression_p(expression e)
The expression is of kind "a", where "a" is a field of some struct "s".
Definition: expression.c:498
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
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
expression make_op_exp(char *op_name, expression exp1, expression exp2)
================================================================
Definition: expression.c:2012
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
Ppolynome expression_to_polynome(expression exp)
===========================================================================
Definition: expression.c:3650
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
entity expression_variable(expression e)
Definition: expression.c:532
bool expression_range_p(expression e)
Definition: expression.c:1848
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
expression syntax_to_expression(syntax s)
generates an expression from a syntax
Definition: expression.c:3581
type ultimate_type(type)
Definition: type.c:3466
int effect_type_depth(type)
Number of steps to access the lowest leave of type t.
Definition: type.c:4948
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
int SizeOfIthDimension(entity, int)
this function returns the size of the ith dimension of a variable e.
Definition: size.c:453
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
size_t type_depth(type)
Number of steps to access the lowest leave of type t without dereferencing.
Definition: type.c:4880
type make_scalar_integer_type(_int)
Definition: type.c:712
_int SizeOfElements(basic)
This function returns the length in bytes of the Fortran or C type represented by a basic,...
Definition: size.c:297
int NumberOfDimension(entity)
Definition: size.c:588
#define value_undefined
Definition: ri.h:3016
#define loop_body(x)
Definition: ri.h:1644
#define basic_pointer(x)
Definition: ri.h:637
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference_p(x)
Definition: ri.h:2728
#define transformer_undefined
Definition: ri.h:2847
#define transformer_undefined_p(x)
Definition: ri.h:2848
#define storage_formal_p(x)
Definition: ri.h:2522
#define syntax_reference(x)
Definition: ri.h:2730
#define normalized_linear_p(x)
Definition: ri.h:1779
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define range_upper(x)
Definition: ri.h:2290
#define storage_tag(x)
Definition: ri.h:2515
#define type_tag(x)
Definition: ri.h:2940
#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 code_declarations(x)
Definition: ri.h:784
@ is_syntax_reference
Definition: ri.h:2691
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define subscript_indices(x)
Definition: ri.h:2563
@ is_storage_rom
Definition: ri.h:2494
@ is_storage_ram
Definition: ri.h:2492
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define transformer_relation(x)
Definition: ri.h:2873
#define transformer_arguments(x)
Definition: ri.h:2871
#define dimension_upper(x)
Definition: ri.h:982
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define range_lower(x)
Definition: ri.h:2288
#define variable_dimensions(x)
Definition: ri.h:3122
#define predicate_system_(x)
Definition: ri.h:2068
#define storage_ram(x)
Definition: ri.h:2521
#define loop_range(x)
Definition: ri.h:1642
#define call_arguments(x)
Definition: ri.h:711
@ is_type_variable
Definition: ri.h:2900
#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 type_variable_p(x)
Definition: ri.h:2947
#define predicate_system(x)
Definition: ri.h:2069
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
#define loop_index(x)
Definition: ri.h:1640
#define variable_basic(x)
Definition: ri.h:3120
#define ram_offset(x)
Definition: ri.h:2251
void sc_base_add_variable(Psysteme sc, Variable var)
Definition: sc.c:248
Psysteme sc_variable_rename(Psysteme s, Variable v_old, Variable v_new)
Psysteme sc_variable_rename(Psysteme s, Variable v_old, Variable v_new): reecriture du systeme s remp...
Definition: sc.c:157
bool sc_weak_consistent_p(Psysteme sc)
check that sc is well defined, that the numbers of equalities and inequalities are consistent with th...
Definition: sc.c:362
bool sc_rn_p(Psysteme sc)
bool sc_rn_p(Psysteme sc): check if the set associated to sc is the whole space, rn
Definition: sc_alloc.c:369
Psysteme sc_empty(Pbase b)
Psysteme sc_empty(Pbase b): build a Psysteme with one unfeasible constraint to define the empty subsp...
Definition: sc_alloc.c:319
Psysteme sc_rn(Pbase b)
Psysteme sc_rn(Pbase b): build a Psysteme without constraints to define R^n, where n is b's dimension...
Definition: sc_alloc.c:336
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_fix(Psysteme s)
fix system s for coherency of the base and number of things.
Definition: sc_alloc.c:141
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
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
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_new(void)
Psysteme sc_new(): alloue un systeme vide, initialise tous les champs avec des valeurs nulles,...
Definition: sc_alloc.c:55
bool sc_empty_p(Psysteme sc)
bool sc_empty_p(Psysteme sc): check if the set associated to sc is the constant sc_empty or not.
Definition: sc_alloc.c:350
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
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
Psysteme sc_copy(Psysteme ps)
Psysteme sc_copy(Psysteme ps): duplication d'un systeme (allocation et copie complete des champs sans...
Definition: sc_alloc.c:230
Psysteme sc_safe_elim_redund(Psysteme ps)
Same as above, but the basis is preserved and sc_empty is returned is the system is not feasible.
#define level
Psysteme sc_safe_append(Psysteme s1, Psysteme s2)
Psysteme sc_safe_append(Psysteme s1, Psysteme s2) input : output : calcul de l'intersection des polye...
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_normalize2(volatile Psysteme ps)
Psysteme sc_normalize2(Psysteme ps): normalisation d'un systeme d'equation et d'inequations lineaires...
Psysteme sc_strong_normalize3(Psysteme ps)
Psysteme sc_strong_normalize5(Psysteme ps, char *(*variable_name)(Variable))
Psysteme sc_strong_normalize4(Psysteme ps, char *(*variable_name)(Variable))
Psysteme sc_strong_normalize4(Psysteme ps, char * (*variable_name)(Variable))
Psysteme sc_strong_normalize2(volatile Psysteme ps)
Psysteme sc_strong_normalize2(Psysteme ps)
Psysteme sc_safe_normalize(Psysteme ps)
Psysteme sc_safe_normalize(Psysteme ps) output : ps, normalized.
Psysteme sc_normalize(Psysteme ps)
Psysteme sc_normalize(Psysteme ps): normalisation d'un systeme d'equation et d'inequations lineaires ...
Psysteme sc_strong_normalize(Psysteme ps)
Psysteme sc_strong_normalize(Psysteme ps)
void sc_transform_eg_in_ineg(Psysteme sc)
Package sc.
Pcontrainte constraints_sort_with_compare(Pcontrainte c, Pbase sort_base, constraint_cmp_func_t compare, void *context)
void sc_vect_sort(Psysteme s, int(*compare)(Pvecteur *, Pvecteur *))
the name is self explanatory, I guess.
Definition: sc_unaires.c:116
void vect_chg_sgn(Pvecteur v)
void vect_chg_sgn(Pvecteur v): multiplie v par -1
Definition: scalaires.c:151
#define semantics_user_warning
transformer any_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
A set of functions to compute the transformer associated to an expression evaluated in a given contex...
Definition: expression.c:4993
transformer add_index_range_conditions(transformer pre, entity i, range r, transformer tfb)
Definition: loop.c:711
bool value_mappings_compatible_vector_p(Pvecteur iv)
transform a vector based on variable entities into a vector based on new value entities when possible...
Definition: mappings.c:924
transformer load_statement_transformer(statement)
s1
Definition: set.c:247
return(s1)
#define ifdebug(n)
Definition: sg.c:47
Pvecteur vecteur
struct Scontrainte * succ
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
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
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: delay.c:253
transformer transformer_range(transformer tf)
Return the range of relation tf in a newly allocated transformer.
Definition: transformer.c:714
transformer transformer_temporary_value_projection(transformer tf)
Definition: transformer.c:1149
const char * external_value_name(entity)
Definition: value.c:753
entity entity_to_intermediate_value(entity)
Definition: value.c:879
const char * pips_user_value_name(entity)
This function is called many times when the constraints and the system of constraints are sorted usin...
Definition: value.c:815
entity entity_to_old_value(entity)
Definition: value.c:869
#define sc_equal_p(ps1, ps2)
Definition: union-local.h:83
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_val(v)
#define vecteur_var(v)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
struct Svecteur * Pbase
struct Svecteur * Pvecteur
#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 term_cst(varval)
#define base_dimension(b)
#define BASE_NULLE
MACROS SUR LES BASES.
#define BASE_NULLE_P(b)
Pbase vect_copy(Pvecteur b)
direct duplication.
Definition: alloc.c:240
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
Pbase base_dup(Pbase b)
Pbase base_dup(Pbase b) Note: this function changes the value of the pointer.
Definition: alloc.c:268
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_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_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
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_sort_in_place(Pvecteur *pv, int *compare)
void vect_sort_in_place(pv, compare) Pvecteur *pv; int (*compare)(Pvecteur *, Pvecteur *);
Definition: unaires.c:290
bool vect_contains_variable_p(Pvecteur v, Variable var)
bool vect_contains_variable_p(Pvecteur v, Variable var) BA 19/05/94 input : a vector and a variable o...
Definition: unaires.c:415
bool vect_common_variables_p(Pvecteur v1, Pvecteur v2)
bool vect_common_variables_p(Pvecteur v1, v2) BA 19/05/94 input : two vectors.
Definition: unaires.c:397