PIPS
alias_propagation.c
Go to the documentation of this file.
1 /*
2 
3  $Id: alias_propagation.c 23065 2016-03-02 09:05:50Z coelho $
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 /******************************************************************
28  *
29  * ALIAS PROPAGATION
30  *
31  *
32 *******************************************************************/
33 
34 /* Aliasing occurs when two or more variables refer to the same storage
35  location at the same program point. This phase tries to compute as
36  precise as possible the interprocedural alias information in a whole
37  program.
38 
39  In Fortran 77, there are several ways to create aliases:
40 
41  1. EQUIVALENCE: two or more entities in the same program unit share
42  storages units
43  2. COMMON: associates different variables in different subprograms
44  with the same storage
45  3. An actual argument is passed to different formal parameters
46  4. A global variable is passed as an actual argument and a variable
47  aliased to the global variable is passed as another actual argument
48  => alias between the two corresponding formal parameters.
49  5. Formal parameters aliases can be passed through chains of calls.
50 
51  The basic idea for computing interprocedural aliases is to follow all
52  possible chains of argument-parameters and nonlocal variable-parameter
53  bindings at all call sites. The call graph of program is traversed in
54  invocation order, and alias information is accumulated incrementally.
55 
56  We use the newgen structure alias_association = (formal_parameter,section,
57  offset, call_path) to store alias information for each formal parameter
58  of each module. Call_path = list of call_sites, call_site = (caller,
59  ordering of the call site) (this is the only current way to store the
60  location of a call site).
61 
62  Let ai be the considering actual argument in the current call site, by
63  separating the treatment of formal parameters from the treatment of
64  global variables, we only have to treat the following case:
65 
66  1. Alias between formal parameter and common variable
67  A global variable can only become aliased to a formal parameter in a
68  routine in which it is visible and only by its being passed as an
69  actual argument to that formal parameter.
70 
71  1.1 Alias created by only one call:
72 
73  Case 1. ai is a common variable and is visible in the current module or in
74  at least one callee (direct and indirect) of this module => add alias
75  association for fi with section of the common : TOP-LEVEL:~FOO
76 
77  1.2 Alias created through chain of calls:
78 
79  Case 2. ai is a formal variable with a common section and this common is
80  visible in the current module or in at least one callee (direct and
81  indirect) of this module => add alias association for fi with section
82  of the common : TOP-LEVEL:~FOO and path = path(formal ai) + (C,ordering)
83 
84  => useless tests between fi and other variables in the same common block with
85  ai, if not take into account the size of ai (assumption: no [interprocedural]
86  array bound violation), because the section is not enough (unique)
87 
88  2. Alias between formal parameters
89 
90  2.1 Alias created by only one call:
91 
92  Case 3. An actual argument is bound to different formal parameters or there are
93  different actual arguments but equivalent. So for a call site, we can divide the
94  argument list into groups of same actual or equivalence arguments. For
95  example:
96  EQUIVALENCE (V1(1,1),V2(5))
97  EQUIVALENCE (U,W)
98  CALL FOO(V1,A,B(TR(I)),C,B(TR(K)),B(H),V1(I,J),V2(K),C,A,M,U,W)
99  SUBROUTINE FOO(F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13)
100  => (F1,F7,F8), (F2,F10), (F3,F5,F6),(F4,F9), (F12,F13)
101 
102  We add alias associations for these formal parameters, all parameters in a
103  same group have same and unique section, path = {(C,ordering)}.
104  The difference among the group (F1,F7,F8), (F12,F13) and the others is that
105  we need to know the initial offsets of F1, F7, F8 and F12, F13 because they
106  can be different variables, and their sections are ram section. For the other
107  cases, we can use section = ALIAS_SPECIAL_i, initial_off = 0.
108 
109  => useless tests ??? Not for same variables because the section is unique but
110  useless tests for equivalence variables, as U and V1 have the same section
111  => test between F8,F12, ...
112 
113  2.2 Alias created through chain of calls
114 
115  Case 4. Actual arguments are formal variables of the caller and have same
116  section from two included call paths.
117  ai, aj : formal variables, same section, call_path(ai) (is) include(s/d)
118  call_path(aj); add alias association for fi with call_path = path_formal(ai)
119  + (C,ordering)
120 
121  Case 5. Actual argument is a formal variable that has same section with other
122  actual argument that is a common variable:
123 
124  5.1 If ai is the formal variable => add alias association for fi with
125  call_path = path_formal(ai) + (C,ordering)
126 
127  5.2 If ai is the common variable => add alias association for fi with
128  call_path = (C,ordering)
129 
130  To compute the offset, we do not use preconditions that may be corrupted by
131  alias violation */
132 
133 #include <stdio.h>
134 #include <stdlib.h>
135 #include <string.h>
136 
137 #include "genC.h"
138 
139 #include "linear.h"
140 #include "ri.h"
141 #include "effects.h"
142 #include "alias_private.h"
143 #include "ri-util.h"
144 #include "prettyprint.h" // for debugging
145 #include "effects-util.h"
146 #include "database.h"
147 #include "pipsdbm.h"
148 #include "resources.h"
149 #include "misc.h"
150 #include "properties.h"
151 #include "transformer.h"
152 #include "instrumentation.h"
153 #include "text-util.h"
154 #include "transformations.h"
155 #include "callgraph.h" // for module_is_called_by_main_program_p
156 #include "alias-classes.h"
157 
158 #define ALIAS_SECTION "ALIAS_SECTION"
159 
160 /* Define a static stack and related functions to remember the current
161  statement */
162 
164 
167 static const char* caller_name;
172 static int number_of_known_offsets = 0;
174 static int unique_section_number = 0;/* Special alias section counter*/
175 
177 {
178  user_log("\n Number of added alias associations: %d",number_of_alias_associations);
179  user_log("\n Number of known offsets: %d",number_of_known_offsets);
180  user_log("\n Number of unknown offsets: %d",number_of_unknown_offsets);
181  user_log("\n Number of processed modules: %d\n",number_of_processed_modules);
182 }
183 
184 /* This function translates an expression e1 from the frame of module 1
185  to the frame of module 2
186  1.If e1 is a reference:
187  1.1. Common variable in mod1 => return corresponding common variable e2 in mod2
188  1.2. Special case : e1 is a formal parameter in mod1, mod2 is caller of mod1
189  => take corresponding actual argument e2 in call c
190  1.3. From the association information, if we have e1 = e2 where e2
191  is constant or contains variables of the mod2 => return e2
192  2.If e1 is a call :
193  2.1. Storage rom : numerical constant or symbolic value (PARAMETER) => return e1
194  2.2. Recursive : e1 = ex1 * ey1
195  ex2 = translate_to_module_frame(mod1,mod2,ex1,c)
196  ey2 = translate_to_module_frame(mod1,mod2,ey1,c)
197  => return e2=ex2*ey2
198  3.If e1 is a range : error
199 
200  Return expression_undefined if we can not translate*/
201 
203 {
204  if (!expression_undefined_p(e1)) {
205  syntax syn = expression_syntax(e1);
206  tag t = syntax_tag(syn);
207  switch(t){
208  case is_syntax_reference:
209  {
212  normalized ne;
213  if (variable_in_common_p(en))
214  {
215  /* Check if the common variable is also declared in the mod2 or not
216  * We can use ram_shared which contains a list of aliased variables with en
217  * but it does not work ????
218  * Another way : looking for a variable in the declaration of the mod2
219  * that has the same offset in the same common block */
220  list l_decls = code_declarations(entity_code(mod2));
221  MAP(ENTITY, enti,{
222  if (same_scalar_location_p(en,enti))
223  {
224  pips_debug(4,"\nThe common variable %s is translated\n",entity_local_name(en));
225  if (array_entity_p(enti))
226  {
227  /* ATTENTION : enti may be an array, such as A(2):
228  COMMON C1,C2,C3,C4,C5
229  COMMON C1,A(2,2)
230  we must return A(1,1), not A */
231  variable varenti = type_variable(entity_type(enti));
232  int len = gen_length(variable_dimensions(varenti));
233  list l_inds = make_list_of_constant(1,len);
234  reference refer = make_reference(enti,l_inds);
235  return reference_to_expression(refer);
236  }
237  return entity_to_expression(enti);
238  }
239  },l_decls);
240  // return the common variable although it is not declared in the module !!!!!!
241  // return entity_to_expression(en);
242  }
244  {
246  entity fun = call_function(c);
247  if (same_entity_p(fun,mod1))
248  {
249  /* Special case : e1 is a formal parameter in mod1, mod2 is caller of mod1
250  miss a check : mod2 = caller of mod1 => can be wrong !!!*/
251  int off = formal_offset(fo);
252  list l_args = call_arguments(c);
253  pips_debug(4,"\nThe formal parameter %s is translated to the caller's frame\n",
254  entity_local_name(en));
255  return find_ith_argument(l_args,off);
256  }
257  }
258  /* Use the association of the call site:
259  Take only the equalities.
260  Project all variables belonging to mod1 , except the current variable e1
261  there are 2 cases :
262  1. The projection is not exact , there are over flows
263  Return the SC_UNDEFINED => what to do, like before ?
264  2. The result is exact, three small cases:
265  2.1 The system is always false sc_empty => unreachable code ?
266  2.2 The system is always true sc_rn => we have nothing ?
267  2.3 The system is parametric =>
268 
269  Look for equality that contain e1
270  Delete e1 from the vector
271  Check if the remaining of the vectors contains only constant (TCTS)
272  or variables of mod2 => return*/
273  if (expression_equal_integer_p(e1,0)) return e1;
275  ne = NORMALIZE_EXPRESSION(e1);
276  if (normalized_linear_p(ne))
277  {
278  Pvecteur ve = normalized_linear(ne);
279  Variable vare = var_of(ve);
281  Psysteme ps_tmp = predicate_system(transformer_relation(binding_context));
282  Pbase b_tmp = ps_tmp->base;
283  /* Attention : here the transformer binding_context is consistent
284  but not the system ps_tmp. I do not understand why ?
285  fprintf(stderr, "consistent psystem ps_tmp before");
286  pips_assert("consistent psystem ps_tmp", sc_consistent_p(ps_tmp));*/
287  if (base_contains_variable_p(b_tmp,vare))
288  {
289  Psysteme ps = sc_dup(ps_tmp);
290  Pbase b = ps->base;
291  Pvecteur pv_var = VECTEUR_NUL;
292  for(; !VECTEUR_NUL_P(b); b = b->succ)
293  {
294  Variable var = vecteur_var(b);
295  if ((strcmp(module_local_name(mod1),entity_module_name((entity)var))==0)
296  && (var!=vare))
297  vect_add_elem(&pv_var, var, VALUE_ONE);
298  }
300  ps->nb_ineq = 0;
301  ps = sc_system_projection_along_variables(ps, pv_var);
302  vect_rm(pv_var);
303  if (ps != SC_UNDEFINED)
304  {
305  // the projection is exact
306  Pcontrainte egal, egal1;
307  for (egal = ps->egalites; egal != NULL; egal = egal1)
308  {
309  /* Take only the equations of the system */
310  Pvecteur vec = egal->vecteur;
311  if (vect_contains_variable_p(vec,vare))
312  {
313  Value vale = vect_coeff(vare,vec);
314  Pvecteur newv = VECTEUR_UNDEFINED;
315  if (value_one_p(vale) || value_mone_p(vale))
316  newv = vect_del_var(vec,vare);
317  if (value_one_p(vale))
318  vect_chg_sgn(newv);
319  if (!VECTEUR_UNDEFINED_P(newv))
320  {
321  /*the coefficient of e is 1 or -1.
322  Check if the remaining vector contains only constant
323  or variavbles of mod2*/
324  Pvecteur v;
325  bool check = true;
326  for (v = newv; (v !=NULL) && (check); v = v->succ)
327  {
328  Variable var = v->var;
329  if ((var != TCST) &&
330  (strcmp(module_local_name(mod2),entity_module_name((entity)var))!=0))
331  check = false;
332  }
333  if (check)
334  {
335  pips_debug(4,"\nThe variable %s is translated by using binding information\n",
336  entity_local_name(en));
337  return Pvecteur_to_expression(newv);
338  }
339  vect_rm(newv);
340  }
341  }
342  egal1 = egal->succ;
343  }
344  }
345  sc_rm(ps);
346  }
347  }
348  break;
349  }
350  case is_syntax_call:
351  {
352  call ca = syntax_call(syn);
353  entity fun = call_function(ca);
354  list l_args = call_arguments(ca);
355  if (l_args==NIL)
356  {
357  /* Numerical constant or symbolic value (PARAMETER) */
358  ifdebug(4)
359  {
360  pips_debug(4,"\nNumerical constant or symbolic value is translated\n");
361  print_expression(e1);
362  }
363  return e1;
364  }
365  /* e1 is a call, not a constant
366  Recursive : with the arguments of the call
367  As our generated expression e1 is a call with operators : +,-,* only,
368  we treat only these cases */
369  if (gen_length(l_args)==1)
370  {
371  expression ex1 = EXPRESSION(CAR(l_args));
372  expression ex2 = translate_to_module_frame(mod1, mod2,ex1,c);
373  if (!expression_undefined_p(ex2))
374  return MakeUnaryCall(fun,ex2);
375  }
376  if (gen_length(l_args)==2)
377  {
378  expression ex1 = EXPRESSION(CAR(l_args));
379  expression ey1 = EXPRESSION(CAR(CDR(l_args)));
380  expression ex2 = translate_to_module_frame(mod1,mod2,ex1,c);
381  expression ey2 = translate_to_module_frame(mod1,mod2,ey1,c);
383  return MakeBinaryCall(fun,ex2,ey2);
384  }
385  break;
386  }
387  default:
388  pips_internal_error("Abnormal cases ");
389  break;
390  }}
391  return expression_undefined;
392 }
393 
394 static void ram_variable_add_aliases(call c,call_site cs,entity actual_var,
395  entity formal_var,expression subval)
396 {
397  storage s = entity_storage(actual_var);
398  ram r = storage_ram(s);
399  entity sec = ram_section(r);
400  int initial_off = ram_offset(r),end_off = -1;
401  list path = CONS(CALL_SITE,cs,NIL);
404  if (array_entity_p(actual_var))
405  {
406  int tmp;
407  if (SizeOfArray(actual_var, &tmp))
408  end_off = tmp - SizeOfElements(variable_basic(type_variable(entity_type(actual_var)))) + initial_off;
409  }
410  else
411  end_off = initial_off;
412  ifdebug(4)
413  {
414  fprintf(stderr, "\nActual argument %s is a ram variable",entity_name(actual_var));
415  fprintf(stderr,"\nwith initial ram offset %d and end offset %d",initial_off,end_off);
416  }
417  if (expression_equal_integer_p(subval,0))
418  /* The offset of actual variable is an integer
419  that can always be translated into the module's frame*/
420  off = int_to_expression(initial_off);
421  else
422  {
423  /* We must translate the subscript value from current caller to the
424  current module's frame by using binding information. This value must be
425  multiplied by the size of array element (number of numerical/character
426  storage units, according to Fortran standard, in PIPS 1 storage unit=1 byte)*/
428  ifdebug(4)
429  {
430  fprintf(stderr, "\nSubval expression before translation:");
431  print_expression(subval);
432  fprintf(stderr, "\nSubval expression after translation:");
433  print_expression(new_subval);
434  }
435  if (!expression_undefined_p(new_subval))
436  {
437  /* subval is translated to the module's frame */
438  if (initial_off ==0)
439  off = copy_expression(new_subval);
440  else
442  int_to_expression(initial_off),
443  copy_expression(new_subval));
444  }
445  }
446  if (expression_undefined_p(off))
448  else
450  /* Attention: normalization of an expression equal to 0 returns a Pvecteur null*/
451  /* initial_off <= off <= initial_off + SizeOfArray - SizeOfElement (no bound violation ;-))*/
452  one_alias = make_alias_association(formal_var,sec,off,initial_off,end_off,path);
454  message_assert("alias_association is consistent",
455  alias_association_consistent_p(one_alias));
456  ifdebug(2)
457  print_alias_association(one_alias);
459  CONS(ALIAS_ASSOCIATION,one_alias, NIL));
460 }
461 
462 /* This function tests if a common com (TOP_LEVEL:~FOO) is visible
463  in the module mod or in at least one callee (direct and indirect)
464  of this module */
465 
466 static bool common_is_visible_p(entity sec, entity mod)
467 {
468  list l_decl = code_declarations(entity_code(mod));
469  /* search for the common declaration in the list */
470  MAP(ENTITY, ei,
471  {
472  storage si = entity_storage(ei);
473  if (storage_ram_p(si))
474  {
475  entity seci = ram_section(storage_ram(si));
476  if (same_entity_p(sec,seci))
477  return true;
478  }
479  }, l_decl);
480  /* search for the common declaration in the callees */
481  if (!entity_main_module_p(mod))
482  {
483  const char* mod_name = module_local_name(mod);
484  callees all_callees = (callees) db_get_memory_resource(DBR_CALLEES,mod_name,true);
485  list l_callees = callees_callees(all_callees);
486  MAP(STRING,callee_name,
487  {
489  if (common_is_visible_p(sec,current_callee)) return true;
490  },l_callees);
491  }
492  return false;
493 }
494 
495 /********************************************************************
496  The following functions are for the case of there is a formal variable
497  that have the same section sec in the argument list l.
498 
499  Look for actual arguments that are formal parameters => take
500  alias_associations of the current caller => compare if they have
501  section = sec or not.
502 *********************************************************************/
503 
505  list actual_path,list l,list l_aliases)
506 {
508  {
510  {
513  if (!same_entity_p(var,actual_var))
514  {
515  storage si = entity_storage(var);
516  if (storage_formal_p(si))
517  {
519  {
520  entity formal_var = alias_association_variable(aa);
521  if (same_entity_p(formal_var,var))
522  {
523  entity formal_sec = alias_association_section(aa);
524  list formal_path = alias_association_call_chain(aa);
525  if (same_entity_p(formal_sec,sec) &&
526  included_call_chain_p(actual_path,formal_path))
527  {
528  /* INCLUDED CALL CHAIN ????????*/
529  pips_debug(3,"\nAliases from an actual argument that is a formal parameter and has same section with other actual argument (the last one can be a common variable or another formal variable).\n");
530  return true;
531  }
532  }
533  },
534  l_aliases);
535  }
536  }
537  }
538  },l);
539  return false;
540 }
541 
542 /********************************************************************
543  The following functions are for the case of there is a common variable
544  that has the same section sec in the argument list l.
545 *********************************************************************/
546 
548 {
550  {
552  {
555  if (variable_in_common_p(var))
556  {
557  storage si = entity_storage(var);
558  entity seci = ram_section(storage_ram(si));
559  if (same_entity_p(seci,sec))
560  {
561  pips_debug(3,"\nAliases from an actual argument that is a common variable and has same section with other actual argument that is a formal variable.\n");
562  return true;
563  }
564  }
565  }
566  },l);
567  return false;
568 }
569 
570 /***************************************************************************
571  The following functions are for the cases: in the actual argument list,
572  there is a formal variable:
573 
574  Case 2. that has a common section and this common is visible in the current
575  module or in at least one callee (direct and indirect) of this module
576 
577  Case 4. that has same section with other formal variable from two included call
578  paths.
579 
580  Case 5.1 that has same section with other common variable in the argument list
581 ****************************************************************************/
582 
583 static void formal_variable_add_aliases(call c,call_site cs, entity actual_var,
584  entity formal_var,expression subval,list l_actuals)
585 {
586  list l_caller_aliases = alias_associations_list((alias_associations)
587  db_get_memory_resource(DBR_ALIAS_ASSOCIATIONS,caller_name,true));
588  pips_debug(2,"\nActual argument %s is a formal parameter",
589  entity_name(actual_var));
591  {
592  entity caller_var = alias_association_variable(aa);
593  if (same_entity_p(caller_var,actual_var))
594  {
595  /* a gen_full_copy_list here is to copy the list and its contain
596  without this : gen_write => gen_trav ....=> bug unknown type 1
597  because the CDR of path point to
598  a newgen data in the caller which is freed before , no more in the memory */
600  list actual_path = alias_association_call_chain(aa);
602  || same_section_formal_variable_in_list_p(actual_var,sec,actual_path,l_actuals,l_caller_aliases)
603  || same_section_common_variable_in_list_p(sec,l_actuals))
604  {
608  expression initial_off = alias_association_offset(aa);
609  /* To be modified : init_off = lower_offset ...*/
610 
611  int init_off = -1;
612  int end_off = -1;
613  // path = gen_nconc(path,gen_full_copy_list(alias_association_call_chain(aa)));
614  ifdebug(3)
615  fprintf(stderr,"\nEntry for %s found in the alias_association",
616  entity_name(caller_var));
617  /* If offset of aa is not expression_undefined, we must translate
618  it to the module's frame by using binding information */
619  if (!expression_undefined_p(initial_off))
620  {
622  initial_off,c);
623  ifdebug(3)
624  {
625  fprintf(stderr, "\nInitial offset expression before translation: \n");
626  print_expression(initial_off);
627  fprintf(stderr, "\nInitial offset expression after translation: \n");
628  print_expression(new_initial_off);
629  }
630  if (!expression_undefined_p(new_initial_off))
631  {
632  if (expression_equal_integer_p(subval,0))
633  off = copy_expression(new_initial_off);
634  else
635  {
636  /* We must translate the subscript value from current caller to the
637  current module's frame by using binding information. This value must be
638  multiplied by the size of array element (number of numerical/character
639  storage units, according to Fortran standard, in PIPS 1 storage unit=1 byte)*/
641  copy_expression(subval),c);
642  ifdebug(3)
643  {
644  fprintf(stderr, "\n Subval expression before translation: \n");
645  print_expression(subval);
646  fprintf(stderr, "\n Subval expression after translation: \n");
647  print_expression(new_subval);
648  }
649  if (!expression_undefined_p(new_subval))
651  copy_expression(new_initial_off),
652  copy_expression(new_subval));
653  }
654  if (expression_constant_p(new_initial_off))
655  {
656  init_off = expression_to_int(new_initial_off);
657  if (array_entity_p(actual_var))
658  {
659  int tmp;
660  if (SizeOfArray(actual_var, &tmp))
661  end_off = tmp - SizeOfElements(variable_basic(type_variable(entity_type(actual_var))))
662  + init_off;
663  }
664  else
665  end_off = init_off;
666  }
667  }
668 
669  }
670  if (expression_undefined_p(off))
672  else
674  /* init_off <= off <= init_off + SizeOfArray - SizeOfElement (no bound violation ;-))*/
675  one_alias = make_alias_association(formal_var,sec,off,init_off,end_off,path);
676  message_assert("alias_association is consistent",
677  alias_association_consistent_p(one_alias));
678  ifdebug(2)
679  print_alias_association(one_alias);
682  CONS(ALIAS_ASSOCIATION,one_alias, NIL));
683  }
684  }
685  },
686  l_caller_aliases);
687 }
688 
689 /********************************************************************
690  The following functions are for the case of same or equivalence actual arguments
691 *********************************************************************/
692 
694 {
695  list retour = NIL;
696  int j;
697  for (j=1;j<=(int)gen_length(l);j++)
698  {
701  {
704  if (same_entity_p(var,e))
705  retour = CONS(INT,j,retour);
706  else
707  if (entities_may_conflict_p(var,e) &&
709  {
711  retour = CONS(INT,j,retour);
712  }
713  }
714  }
715  return retour;
716 }
717 
718 /* Add alias_association for each formal variable whose offset is in the list l*/
720  list l_actual,bool equiv)
721 {
722  if (equiv)
723  {
724  MAP(INT,k,
725  {
726  expression actual_arg = find_ith_argument(l_actual,k);
727  reference actual_ref = expression_reference(actual_arg);
728  entity actual_var = reference_variable(actual_ref);
730  list l_actual_inds = reference_indices(actual_ref);
731  expression subval = subscript_value_stride(actual_var,l_actual_inds);
732  ram_variable_add_aliases(c,cs,actual_var,formal_var,subval);
733  },l);
734  }
735  else
736  {
737  string istr = int2a(unique_section_number++);
738  string ename = strdup(concatenate(ALIAS_SECTION,istr,NULL));
740  free(ename);
741  free(istr);
742  MAP(INT,k,
743  {
744  expression actual_arg = find_ith_argument(l_actual,k);
745  reference actual_ref = expression_reference(actual_arg);
746  entity actual_var = reference_variable(actual_ref);
748  list l_actual_inds = reference_indices(actual_ref);
749  expression subval = subscript_value_stride(actual_var,l_actual_inds);
751  int end_off = -1;
753  list path = CONS(CALL_SITE,cs,NIL);
754  if (array_entity_p(actual_var))
755  {
756  int tmp;
757  if (SizeOfArray(actual_var, &tmp))
758  end_off = tmp - SizeOfElements(variable_basic(type_variable(entity_type(actual_var))));
759  }
760  else
761  end_off = 0;
762  if (expression_equal_integer_p(subval,0))
763  /* The offset of the actual variable is an integer
764  that can always be translated into the module's frame*/
765  off = int_to_expression(0);
766  else
767  {
769  ifdebug(4)
770  {
771  fprintf(stderr, "\nSubval expression before translation: \n");
772  print_expression(subval);
773  fprintf(stderr, "\nSubval expression after translation: \n");
774  print_expression(off);
775  }
776  }
777  if (expression_undefined_p(off))
779  else
781  /* 0 <= off <= 0 + array_size_stride (no bound violation ;-))*/
782  one_alias = make_alias_association(formal_var,sec,off,0,end_off,path);
784  message_assert("alias_association is consistent",
785  alias_association_consistent_p(one_alias));
786  ifdebug(2)
787  print_alias_association(one_alias);
789  CONS(ALIAS_ASSOCIATION,one_alias, NIL));
790  },l);
791  }
792 }
793 
795 {
796  if(call_function(c) == current_mod)
797  {
798  statement stmt = current_statement_head();
799  list l_actuals = call_arguments(c);
800  list l = gen_full_copy_list(l_actuals);
801  int order = statement_ordering(stmt);
802  int i = 0;
804  // list path = gen_full_copy_list(CONS(CALL_SITE,cs,NIL));
805  ifdebug(2)
806  {
807  pips_debug(2,"\nCurrent caller: %s", caller_name);
808  fprintf(stderr,"\nCurrent call site:");
810  }
811  message_assert("call_site is consistent", call_site_consistent_p(cs));
812  l_traversed = NIL;
813  FOREACH(EXPRESSION,actual_arg, l)
814  {
815  i++;
816  if (expression_reference_p(actual_arg))
817  {
818  /* Correspond to different cases of alias, we make the following groups and order :
819  Case 3. list_of_same_or_equivalence_arguments
820  Case 1 + Case 5.2. common variable
821  Case 2 + Case 4 + Case 5.1. formal variable */
822  reference actual_ref = expression_reference(actual_arg);
823  entity actual_var = reference_variable(actual_ref);
824  list l_actual_inds = reference_indices(actual_ref);
825  expression subval = subscript_value_stride(actual_var,l_actual_inds);
827  list l_same_or_equiv = NIL;
828  /* To distinguish between equivalence or same argument cases*/
829  int j = gen_length(l_traversed);
830  bool equiv = false;
831  if (!variable_in_list_p(actual_var,l_traversed))
832  {
833  l_same_or_equiv = list_of_same_or_equivalence_arguments(actual_var,l);
834  if ((int)gen_length(l_traversed)>j) equiv = true;
835  l_traversed = CONS(ENTITY,actual_var,l_traversed);
836  }
837  ifdebug(3)
838  {
839  if (equiv)
840  fprintf(stderr,"\nList of equivalent arguments: ");
841  else
842  fprintf(stderr,"\nList of same arguments: ");
843  MAP(INT,l,
844  {
845  fprintf(stderr,"%d,",l);
846  },l_same_or_equiv);
847  }
848  if (gen_length(l_same_or_equiv) > 1)
849  same_or_equivalence_argument_add_aliases(l_same_or_equiv,c,cs,l_actuals,equiv);
850  if (variable_in_common_p(actual_var))
851  {
852  storage s = entity_storage(actual_var);
853  entity sec = ram_section(storage_ram(s));
854  list l_caller_aliases = alias_associations_list((alias_associations)
855  db_get_memory_resource(DBR_ALIAS_ASSOCIATIONS,caller_name, true));
856  if (common_is_visible_p(sec,current_mod) ||
857  same_section_formal_variable_in_list_p(actual_var,sec,NIL,l_actuals,l_caller_aliases))
858  ram_variable_add_aliases(c,cs,actual_var,formal_var,subval);
859  }
860  if (storage_formal_p(entity_storage(actual_var)))
861  formal_variable_add_aliases(c,cs,actual_var,formal_var,subval,l_actuals);
862  }
863  }
864  l_traversed = NIL;
865  gen_free_list(l);
866  }
867  return true;
868 }
869 
871 {
872  statement caller_statement = (statement) db_get_memory_resource
873  (DBR_CODE,caller_name, true);
874  set_ordering_to_statement(caller_statement);
875  make_current_statement_stack();
876  gen_multi_recurse(caller_statement,
877  statement_domain, current_statement_filter,current_statement_rewrite,
879  NULL);
880  free_current_statement_stack();
882 }
883 
885 {
886  /* Traverse each caller and add aliases to the list of aliases (l_current_aliases) */
888  MAP(STRING, c_name,
889  {
892  if (get_bool_property("ALIAS_CHECKING_USING_MAIN_PROGRAM") &&
894  /* If the current caller is never called by the main program =>
895  no need to follow this caller*/
896  pips_user_warning("Module %s is not called by the main program \n",caller_name);
897  else
899  }, l_callers);
900  return l_current_aliases;
901 }
902 
904 {
905  list l_aliases = NIL;
908  // number_of_alias_associations = 0;
910  debug_on("ALIAS_PROPAGATION_DEBUG_LEVEL");
911  pips_debug(1,"\nBegin alias propagation for module %s \n", module_name);
912  /* No alias for main program*/
914  {
915  if (get_bool_property("ALIAS_CHECKING_USING_MAIN_PROGRAM") &&
917  /* If the current module is never called by the main program =>
918  don't need to compute aliases for this module*/
919  pips_user_warning("Module %s is not called by the main program \n",module_name);
920  else
921  {
923  list l_formals = NIL;
924  /* search for formal parameters in the declaration list */
925  MAP(ENTITY, e,
926  {
927  if (formal_parameter_p(e))
928  l_formals = gen_nconc(l_formals,CONS(ENTITY,e,NIL));
929  },l_decls);
930  /* if there is no formal parameter, do nothing */
931  if (l_formals != NIL)
932  {
933  /* Take the list of callers, if there is no caller, do nothing */
934  callees callers = (callees) db_get_memory_resource(DBR_CALLERS,module_name,true);
935  list l_callers = callees_callees(callers);
936  if (l_callers != NIL)
937  {
938  ifdebug(2)
939  {
940  fprintf(stderr,"The list of formal parameters:");
941  print_entities(l_formals);
942  fprintf(stderr,"\nThe list of callers: ");
944  (void) fprintf(stderr, "%s, ", caller_name);
945  }, l_callers);
946  (void) fprintf(stderr, "\n");
947  }
948  l_aliases = alias_propagation_callers(l_callers);
949  }
950  else
951  /* The module has no caller => don't need to compute aliases for this module*/
952  pips_user_warning("\n Module %s has no caller \n",module_name );
953  }
954  }
955  }
956  /* save to resource */
957  DB_PUT_MEMORY_RESOURCE(DBR_ALIAS_ASSOCIATIONS,module_name,make_alias_associations(l_aliases));
961  debug_off();
962  return true;
963 }
964 
965 
966 
967 
968 
969 
970 
971 
void user_log(const char *format,...)
Definition: message.c:234
call_site make_call_site(entity a1, intptr_t a2)
bool call_site_consistent_p(call_site p)
bool alias_association_consistent_p(alias_association p)
Definition: alias_private.c:67
alias_association make_alias_association(entity a1, entity a2, expression a3, intptr_t a4, intptr_t a5, list a6)
Definition: alias_private.c:94
alias_associations make_alias_associations(list a)
Definition: alias_private.c:52
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
bool included_call_chain_p(list l1, list l2)
Definition: alias_check.c:246
void print_alias_association(alias_association aa)
Definition: alias_check.c:301
#define alias_associations_list(x)
Definition: alias_private.h:86
#define CALL_SITE(x)
CALL_SITE.
#define alias_association_section(x)
#define alias_association_variable(x)
#define ALIAS_ASSOCIATION(x)
ALIAS_ASSOCIATION.
Definition: alias_private.h:90
#define alias_association_call_chain(x)
#define alias_association_undefined
Definition: alias_private.h:96
#define alias_association_offset(x)
static void display_alias_propagation_statistics()
Special alias section counter.
static int number_of_unknown_offsets
static void same_or_equivalence_argument_add_aliases(list l, call c, call_site cs, list l_actual, bool equiv)
Add alias_association for each formal variable whose offset is in the list l.
static bool same_section_formal_variable_in_list_p(entity actual_var, entity sec, list actual_path, list l, list l_aliases)
static bool add_aliases_for_current_call_site(call c)
static void add_aliases_for_current_caller()
static entity current_caller
static bool same_section_common_variable_in_list_p(entity sec, list l)
static bool common_is_visible_p(entity sec, entity mod)
This function tests if a common com (TOP_LEVEL:~FOO) is visible in the module mod or in at least one ...
static int number_of_known_offsets
#define ALIAS_SECTION
Aliasing occurs when two or more variables refer to the same storage location at the same program poi...
static list l_traversed
static int number_of_processed_modules
static int number_of_alias_associations
static void ram_variable_add_aliases(call c, call_site cs, entity actual_var, entity formal_var, expression subval)
expression translate_to_module_frame(entity mod1, entity mod2, expression e1, call c)
This function translates an expression e1 from the frame of module 1 to the frame of module 2 1....
bool alias_propagation(char *module_name)
static list alias_propagation_callers(list l_callers)
static entity current_mod
Define a static stack and related functions to remember the current statement.
static list l_current_aliases
static const char * caller_name
static list list_of_same_or_equivalence_arguments(entity e, list l)
static void formal_variable_add_aliases(call c, call_site cs, entity actual_var, entity formal_var, expression subval, list l_actuals)
static int unique_section_number
#define value_mone_p(val)
void const char const char const int
#define value_one_p(val)
int Value
#define VALUE_ONE
@ INT
Definition: atomic.c:48
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
transformer transformer_identity()
Allocate an identity transformer.
Definition: basic.c:110
bool module_is_called_by_main_program_p(entity mod)
Definition: callgraph.c:103
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
Pcontrainte contraintes_free(Pcontrainte pc)
Pcontrainte contraintes_free(Pcontrainte pc): desallocation de toutes les contraintes de la liste pc.
Definition: alloc.c:226
static entity current_callee
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define STRING(x)
Definition: genC.h:87
void free(void *)
bool entities_may_conflict_p(entity e1, entity e2)
Check if two entities may conflict.
Definition: conflicts.c:984
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
void gen_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
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
#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
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#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_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
#define message_assert(msg, ex)
Definition: newgen_assert.h:47
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define DEFINE_LOCAL_STACK(name, type)
int tag
TAG.
Definition: newgen_types.h:92
hash_table set_ordering_to_statement(statement s)
To be used instead of initialize_ordering_to_statement() to make sure that the hash table ots is in s...
Definition: ordering.c:172
void reset_ordering_to_statement(void)
Reset the mapping from ordering to statement.
Definition: ordering.c:185
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
#define PLUS_OPERATOR_NAME
#define NORMALIZE_EXPRESSION(e)
#define binary_intrinsic_expression(name, e1, e2)
bool entity_special_area_p(entity e)
Definition: area.c:154
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
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
bool array_entity_p(entity e)
Definition: entity.c:793
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
code entity_code(entity e)
Definition: entity.c:1098
bool entity_main_module_p(entity e)
Definition: entity.c:700
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
void print_entities(list l)
Definition: entity.c:167
entity find_ith_formal_parameter(entity the_fnct, int rank)
This function gives back the ith formal parameter, which is found in the declarations of a call or a ...
Definition: entity.c:1863
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092
expression reference_to_expression(reference r)
Definition: expression.c:196
expression Pvecteur_to_expression(Pvecteur vect)
AP, sep 25th 95 : some usefull functions moved from static_controlize/utils.c.
Definition: expression.c:1825
void clean_all_normalized(expression e)
Definition: expression.c:4102
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
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 find_ith_argument(list args, int n)
Definition: expression.c:1147
list make_list_of_constant(int val, int number)
of expression
Definition: expression.c:3369
expression subscript_value_stride(entity arr, list l_inds)
Definition: expression.c:4127
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
bool expression_equal_integer_p(expression exp, int i)
================================================================
Definition: expression.c:1977
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
bool SizeOfArray(entity, int *)
This function computes the total size of a variable in bytes, ie.
Definition: size.c:87
bool variable_is_a_module_formal_parameter_p(entity, entity)
Definition: variable.c:1547
bool variable_in_common_p(entity)
true if v is in a common.
Definition: variable.c:1570
bool same_scalar_location_p(entity, entity)
FI: transferred from semantics (should be used for effect translation as well)
Definition: variable.c:1992
bool formal_parameter_p(entity)
Definition: variable.c:1489
bool variable_in_list_p(entity, list)
Definition: variable.c:1623
_int SizeOfElements(basic)
This function returns the length in bytes of the Fortran or C type represented by a basic,...
Definition: size.c:297
#define formal_offset(x)
Definition: ri.h:1408
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define storage_formal_p(x)
Definition: ri.h:2522
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define normalized_linear_p(x)
Definition: ri.h:1779
#define call_function(x)
Definition: ri.h:709
#define callees_callees(x)
Definition: ri.h:675
#define reference_variable(x)
Definition: ri.h:2326
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define statement_ordering(x)
Definition: ri.h:2454
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define code_declarations(x)
Definition: ri.h:784
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
#define storage_ram_p(x)
Definition: ri.h:2519
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define ram_section(x)
Definition: ri.h:2249
#define storage_formal(x)
Definition: ri.h:2524
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#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 reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define expression_undefined_p(x)
Definition: ri.h:1224
#define variable_dimensions(x)
Definition: ri.h:3122
#define storage_ram(x)
Definition: ri.h:2521
#define call_arguments(x)
Definition: ri.h:711
#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 predicate_system(x)
Definition: ri.h:2069
#define variable_basic(x)
Definition: ri.h:3120
#define ram_offset(x)
Definition: ri.h:2251
void sc_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
void vect_chg_sgn(Pvecteur v)
void vect_chg_sgn(Pvecteur v): multiplie v par -1
Definition: scalaires.c:151
static statement current_statement
#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 nb_ineq
Definition: sc-local.h:73
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: statement.c:54
char * int2a(int)
util.c
Definition: util.c:42
transformer formal_and_actual_parameters_association(call c, transformer pre)
formal_and_actual_parameters_association(call c, transformer pre): Add equalities between actual and ...
Definition: transformer.c:2542
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_var(v)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
#define VECTEUR_UNDEFINED
#define VECTEUR_NUL_P(v)
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 VECTEUR_UNDEFINED_P(v)
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
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
Pvecteur vect_del_var(Pvecteur v_in, Variable var)
Pvecteur vect_del_var(Pvecteur v_in, Variable var): allocation d'un nouveau vecteur egal a la project...
Definition: unaires.c:206
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
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