PIPS
points_to.c
Go to the documentation of this file.
1 /*
2 
3  $Id$
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 /* Interface with points-to library */
29 
30 #include <stdio.h>
31 #include <string.h>
32 
33 #include "genC.h"
34 #include "linear.h"
35 
36 #include "misc.h"
37 #include "properties.h"
38 
39 #include "ri.h"
40 #include "effects.h"
41 
42 #include "ri-util.h"
43 #include "prettyprint.h"
44 #include "effects-util.h"
45 
46 #include "text-util.h"
47 
48 #include "effects-simple.h"
49 
50 #include "transformer.h"
51 //#include "semantics.h"
52 
53 #include "effects-convex.h"
54 
55 #include "pips-libs.h"
56 #ifdef HAVE_PIPS_points_to_LIBRARY
57 // for get_points_to_graph_from_statement & expression_to_points_to_sinks
58 #include "points-to.h" // 2 or more functions
59 
60 
61 /* Substitute PHI1 in effect reference if possible thanks to an
62  * equation in the effect descriptor, which is assumed convex.
63  *
64  */
66 {
67  bool adapt_p = false; // By default, the conversion fails
69  list sl = reference_indices(r); // subscript list
70  if(!ENDP(sl)) {
71  expression se = EXPRESSION(CAR(sl));
72  if(expression_reference_p(se)) {
73  // By definition, it must be a reference to PHI1 variable
75  entity phi = reference_variable(sr);
76  entity phi1 = make_phi_entity(1);
77  if(phi==phi1) {
78  /* Is phi defined as a 0 constant in the convex descriptor of eff?
79  *
80  * The standard way to do this is to call one of the minmax
81  * functions, but they are very slow. And here we know which
82  * equation to expect, phi==0.
83  */
86  Value val;
87  if(sc_value_of_variable(sc, (Variable) phi, &val)) {
88  if(val==VALUE_ZERO) { // No VALUE_ZERO_P predicate in linear.h
89 
90  /* Eliminate phi1 from the subscript list and from the predicate */
92  expression_syntax(se) =
95 
96  // Substitute PHI_n by PHI_{n-1}
97  // They are supposed to appear in increasing rank order
98  list nsl = CDR(sl);
99  FOREACH(EXPRESSION, nse, nsl) {
100  syntax nss = expression_syntax(nse);
101  if(syntax_reference_p(nss)) {
102  reference nsr = syntax_reference(nss);
103  entity phin = reference_variable(nsr);
104  int r = phi_entity_rank(phin);
105  if(r!=0) {
106  entity phinm1 = make_phi_entity(r-1);
107  region_value_substitute(eff, phin, phinm1);
108  // Will be performed after translation
109  // reference_variable(nsr) = phinm1; Replace all phi
110  // variables by zero for matching the points-to
111  // information
113  expression_syntax(nse) =
115  }
116  }
117  }
118  adapt_p = true; // Could now mean that phi1 has been eliminated
119  }
120  }
121  else {
122  /* Phi1 must be preserved, but the corresponding subscript
123  set to zero to exploit points-to information for the
124  translation */
125  /* Eliminate phi1 from the subscript list */
127  expression_syntax(se) =
129  adapt_p = true;
130  }
131  }
132  }
133  }
134 
135  return adapt_p;
136 }
137 
138 /* The same issue must arise in Fortran and be treated as a
139  * case of region backward translation somewhere in
140  * convex-effects.
141  *
142  * phi_n has to be offset by se, if se is an affine expression
143  * or if its value is known.
144  *
145  * Else, phi_n has to be project out of the descriptor, which is
146  * always valid if the exact or must approximation is reduced to may.
147  *
148  * In all cases, the subscript must be updated and 0 be
149  * replaced by phi_n.
150  *
151  * Expression se is the nth subscript of the reference in eff. Effect
152  * eff and expression se are updated by side effects.
153  */
155 {
156  // The easiest implementation
157  //pips_internal_error("Phi update not implemented yet.\n");
158 
160 
161  if(normalized_linear_p(n)) {
162  // Substitue phi_n by pni_n-v in the convex descriptor
164  v = vect_multiply(v, VALUE_MONE);
165  //vect_add_elem(&v, (Variable) phi_n, VALUE_MONE);
166  //Pcontrainte eq = contrainte_make(v);
167  descriptor d = effect_descriptor(eff); // Assumed convex
168  Psysteme sc = descriptor_convex(d);
169  // descriptor_convex(d) = sc_variable_substitution_with_eq_ofl_ctrl(sc, eq, (Variable) phi_n, FWD_OFL_CTRL);
171  }
172  // The expression may not be affine but still be a constant expression
173  // else if(constant_expression_p()) {}
174  else {
175  // The second easiest implementation
179  }
181  expression_syntax(se) =
183 }
184 
185 /* Replace back 0's used for the points-to translation by phi
186  * variables (side effects).
187  *
188  * Rename the original phi variables in the predicate if the dimension
189  * has increased.
190  *
191  * Add equations for the new phi variables.
192  */
194 {
196  list sl = reference_indices(r);
197  int n = 1;
198  bool substituted_p = false;
199  list pl = NIL;
200  FOREACH(EXPRESSION, se, sl) {
201  syntax ss = expression_syntax(se);
202  // FI: I assume that fields are accessed as references
203  if(syntax_call_p(ss)) {
204  entity phi_n = make_phi_entity(n);
205  call c = syntax_call(ss);
206  entity f = call_function(c);
207  entity zero = int_to_entity(0);
208  bool unbounded_p = same_string_p(entity_local_name(f),
210  if(f==zero || unbounded_p) {
212  expression_syntax(se) =
214  substituted_p = true;
215  }
216  if(!substituted_p) {
217  // FI: this function should handle the zero and unbounded cases
219  }
220  if(unbounded_p) {
221  /* The translation is not precise */
222  pl = CONS(ENTITY, phi_n, pl);
223  }
224  }
225  n++;
226  }
227 
228  /* Adapt the phi variables in the predicate when the dimension of
229  * the new effect is strictly larger
230  */
231 
232  reference or = effect_any_reference(old_eff);
233  list osl = reference_indices(or);
234  int od = (int) gen_length(osl);
235  int delta = (int) gen_length(sl) - od;
236  // The new reference has always more subscrits than the old one
237  // Except with constrant strings: "world" and "update2:_p_1[PHI1]"
238  // Because in this case, "world" has not been subscripted...
239  // The internal representation shuold be fixed
240  // pips_assert("delta is positive", delta>=0);
241  if(delta>0) {
242  int i;
243  descriptor d = effect_descriptor(eff); // Assumed convex
244  Psysteme sc = descriptor_convex(d);
245  for(i=1; i<=od; i++) {
246  // Substitute phi_i by phi_{i+delta}
247  entity phi_i = make_phi_entity(i);
248  entity phi_i_plus_delta = make_phi_entity(i+delta);
249  descriptor_convex(d) = sc_variable_rename(sc, phi_i, phi_i_plus_delta);
250  }
251  // Add equations phi_i == 0 if useful
252  list cs = sl;
253  for(i=1;i<=delta;i++) {
254  expression s = EXPRESSION(CAR(cs));
255  if(expression_reference_p(s)) {
257  entity phi = reference_variable(r);
258  if(phi_entity_rank(phi)==i) { // No need to do anything for fields
261  sc = sc_equation_add(sc, c);
262  }
263  else if(entity_field_p(phi)) {
264  // Do nothing
265  ;
266  }
267  else {
269  entity phi_i = make_phi_entity(i);
270  if(unbounded_expression_p(s)) {
271  ; // no information about phi_i
272  }
273  else if(normalized_linear_p(ns)) {
275  vect_add_elem(&v, (Variable) phi_i, VALUE_MONE);
277  sc = sc_equation_add(sc, c);
278  }
279  else {
280  // No information about phi
281  ;
282  }
285  // expression_normalized(s) = NORMALIZE_EXPRESSION(s);
287  }
288  }
289  POP(cs);
290  }
291  }
292 
293  /* Eliminate phi variables that are related to an imprecise translation
294  * and set the approximation to MAY.
295  */
296  if(!ENDP(pl)) {
299  free_approximation(app);
302  }
303 
304  gen_free_list(pl);
305  }
306 
307  return eff;
308 }
309 ␌
310 /* If both "se", source entity, and "de", destination entity, are
311  * defined, substitute the values of "se" by the values of "de" in
312  * "backward_p" mode, when translating a callee transformer at a call
313  * site of a caller.
314  *
315  * If the "se" entity cannot be substituted, its value must be
316  * project.
317  */
318 static effect substitute_scalar_stub_in_convex_array_region(effect eff, entity se, entity de, bool backward_p, list * ppl)
319 {
320  if(entity_undefined_p(se))
321  ;
322  else if(entity_undefined_p(de))
323  *ppl = CONS(ENTITY, se, *ppl);
324  else if(entity_has_values_p(de)) {
325  // Not in the caller's frame
326  // entity nsv = entity_to_new_value(se);
327  entity nsv = se;
328  entity ndv = entity_to_new_value(de);
329  if(backward_p) { // For transformers
330  region_value_substitute(eff, nsv, ndv);
331  }
332  else { // For preconditions
333  region_value_substitute(eff, ndv, nsv);
334  }
335  }
336  else {
337  // FI: could be some debugging stuff
338  pips_user_warning("Stub \"%s\" cannot be substituted.\n",
339  entity_user_name(de));
340  // FI: entity "de" must be projected
341  *ppl = CONS(ENTITY, se, *ppl);
342  }
343  return eff;
344 }
345 ␌
346 static effect substitute_struct_stub_in_convex_array_region(effect eff, reference l, type lt, reference r, type rt __attribute__((unused)), bool backward_p, list *ppl)
347 {
348  list fl = struct_type_to_fields(lt);
349  FOREACH(ENTITY, f, fl) {
351  if(analyzed_type_p(ft)) {
358 
359  if(!entity_undefined_p(l1)) {
360  if(!entity_undefined_p(l2)) {
361  eff = substitute_scalar_stub_in_convex_array_region(eff, l1, l2, backward_p, ppl);
362  }
363  }
364  else {
365  // pips_internal_error("Not implemented yet.\n");
366  // Do nothing, this field may simply be not used
367  ;
368  }
369  free_reference(r1);
370  free_reference(r2); // another option would be to remove the last subscript
371  }
372  else if(type_struct_variable_p(ft)) {
373  // This piece of code could be integrate in the previous
374  // alternative to share most of its code
379  // GO down recursively
380  eff = substitute_struct_stub_in_convex_array_region(eff, l1, ft, r1, ft, backward_p, ppl);
381  }
382  }
383  return eff;
384 }
385 ␌
386 /* Exploit the binding map to substitute calles's stubs by actual
387  * arguments, which may be stubs of the callers,
388  *
389  * backward_p request a substitution from the callees' frame into the
390  * caller's frame, which is useful for transformers. Flag backward_p is
391  * set to false to compute ???
392  */
393 effect substitute_stubs_in_convex_array_region(effect eff, bool backward_p, set binding)
394 {
395  if(pt_to_list_undefined_p()) {
396  // Return eff as is ?
397  ;
398  }
399  else {
400  if(!set_undefined_p(binding)) {
401  list pl = NIL; // FI: I am not sure we can managed forward and
402  // backward projections with one variable
403  SET_FOREACH(points_to, pt, binding) {
406  cell s = points_to_source(pt); // callee
407  cell d = points_to_sink(pt); // caller
410  list srs = reference_indices(sr);
411  list drs = reference_indices(dr);
412  if(ENDP(srs) && ENDP(drs)) {
413  entity se = reference_variable(sr);
414  entity de = reference_variable(dr);
415  if(entity_has_values_p(de))
416  eff = substitute_scalar_stub_in_convex_array_region(eff, se, de, backward_p, &pl);
417  else {
418  type se_t = entity_basic_concrete_type(se);
419  type de_t = entity_basic_concrete_type(de);
420  if(type_struct_variable_p(se_t)) {
421  eff = substitute_struct_stub_in_convex_array_region(eff, sr, se_t, dr, de_t, backward_p, &pl);
422  }
423  else
424  pl = CONS(ENTITY, se, pl);
425  }
426  }
427  else if(ENDP(srs) && !ENDP(drs)) {
428  entity se = reference_variable(sr);
429  if(analyzed_reference_p(dr)) {
431  eff = substitute_scalar_stub_in_convex_array_region(eff, se, de, backward_p, &pl);
432  }
433  else {
434  pl = CONS(ENTITY, se, pl);
435  }
436  }
437  else if(!ENDP(srs) && ENDP(drs)) {
438  entity de = reference_variable(dr);
439  if(entity_has_values_p(de)) {
441  if(!entity_undefined_p(se))
442  eff = substitute_scalar_stub_in_convex_array_region(eff, se, de, backward_p, &pl);
443  else
444  pips_internal_error("Not implemented yet.\n");
445  }
446  else {
447  type de_t = entity_basic_concrete_type(de);
448  if(type_struct_variable_p(de_t)) {
449  eff = substitute_struct_stub_in_convex_array_region(eff, sr, de_t, dr, de_t, backward_p, &pl);
450  }
451  else {
452  // Do nothing
453  // entity se = reference_variable(sr);
454  // pl = CONS(ENTITY, se, pl);
455  ;
456  }
457  }
458  }
459  else { // !ENDP(srs) & !ENDP(drs)
460  if(analyzed_reference_p(dr)) {
463  eff = substitute_scalar_stub_in_convex_array_region(eff, se, de, backward_p, &pl);
464  }
465  else {
468  if(type_struct_variable_p(cst))
469  eff = substitute_struct_stub_in_convex_array_region(eff, sr, cst, dr, cst, backward_p, &pl);
470  else {
471  // No useful information in this binding
472  ;
473  }
474  }
475  }
476  }
477  }
478  if(!ENDP(pl)) {
479  // Get rid on untranslatable entities
480  // pips_internal_error("Not implemented yet.\n");
481  //eff = safe_region_projection(eff, pl);
482  ; // do nothing and let another function perform the clean-up.
483  }
484  }
485  }
486 
487  return eff;
488 }
489 
490 #else // no HAVE_PIPS_points_to_LIBRARY
491 // typedef set points_to_graph
492 
493 // FI: I do not believe we need to declare stubs because the function
494 // above is called from within semantics-generic/points_to.c, by a
495 // function that is guarded too
496 
497 #if false
499  pt_map pt_caller)
500 {
501  pips_internal_error("points-to library not available");
502  return NIL;
503 }
504 #endif
505 #endif // HAVE_PIPS_points_to_LIBRARY
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
approximation make_approximation_may(void)
Definition: effects.c:179
void free_approximation(approximation p)
Definition: effects.c:135
void free_normalized(normalized p)
Definition: ri.c:1407
call make_call(entity a1, list a2)
Definition: ri.c:269
syntax make_syntax_call(call _field_)
Definition: ri.c:2500
void free_reference(reference p)
Definition: ri.c:2050
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
void free_syntax(syntax p)
Definition: ri.c:2445
syntax make_syntax_reference(reference _field_)
Definition: ri.c:2494
#define VALUE_ZERO
void const char const char const int
#define VALUE_MONE
int Value
#define VALUE_ONE
entity int_to_entity(_int c)
Definition: constant.c:453
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
void adapt_phi_n_variable_in_convex_effect(effect, expression, entity)
entity make_phi_entity(int)
void region_value_substitute(effect, entity, entity)
bool adapt_convex_effect_cell_to_backward_translation(effect)
points_to.c
effect substitute_stubs_in_convex_array_region(effect, bool, set)
void region_exact_projection_along_variable(effect, entity)
effect adapt_translation_as_convex_effect(effect, effect)
void region_exact_projection_along_variables(effect, list)
void region_exact_projection_along_variables(effect reg, list l_var) input : a region and a list of v...
int phi_entity_rank(entity)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
bool pt_to_list_undefined_p(void)
points_to.c
entity constant_memory_access_path_to_location_entity(reference)
A constant memory access path may not be considered.
Definition: locations.c:329
#define approximation_exact_p(x)
Definition: effects.h:369
#define effect_descriptor(x)
Definition: effects.h:646
#define approximation_must_p(x)
Definition: effects.h:366
#define descriptor_convex(x)
Definition: effects.h:601
#define effect_approximation(x)
Definition: effects.h:644
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
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 pips_user_warning
Definition: misc-local.h:146
#define pips_internal_error
Definition: misc-local.h:149
#define same_string_p(s1, s2)
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
#define set_undefined_p(s)
Definition: newgen_set.h:49
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
#define points_to_approximation(x)
#define points_to_sink(x)
#define points_to_source(x)
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783
#define UNBOUNDED_DIMENSION_NAME
Definition: ri-util-local.h:74
#define NORMALIZE_EXPRESSION(e)
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 entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
reference add_subscript_to_reference(reference r, expression s)
Add a last subscript expression s to a reference r.
Definition: expression.c:224
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
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
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
list struct_type_to_fields(type)
Definition: type.c:5798
type compute_basic_concrete_type(type)
computes a new type which is the basic concrete type of the input type (this new type is not stored i...
Definition: type.c:3556
bool type_struct_variable_p(type)
Definition: type.c:3867
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference_p(x)
Definition: ri.h:2728
#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 ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define syntax_call_p(x)
Definition: ri.h:2734
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined_p(x)
Definition: ri.h:2762
#define expression_normalized(x)
Definition: ri.h:1249
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
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
Psysteme sc_substitute_dimension(Psysteme s, Variable i, Pvecteur v)
Psysteme sc_substitute_dimension(Psysteme s, Variable i, Pvecteur v): The ith dimension of all constr...
Definition: sc.c:130
bool sc_value_of_variable(Psysteme ps, Variable var, Value *pval)
bool sc_value_for_variable(Psysteme ps, Variable var, Value *pval): examine les egalites du systeme p...
Definition: sc_eval.c:70
Psysteme sc_equation_add(Psysteme sc, Pcontrainte c)
The basis of the constraint system is updated.
Definition: sc_insert_eq.c:101
Pvecteur vect_multiply(Pvecteur v, Value x)
Pvecteur vect_multiply(Pvecteur v, Value x): multiplication du vecteur v par le scalaire x,...
Definition: scalaires.c:123
set user_call_to_points_to_interprocedural_binding_set(call c, pt_map pt_caller)
Compute the binding relations in a complete interprocedural way: be as accurate as possible.
Definition: points_to.c:79
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
bool analyzed_reference_p(reference)
FI: Nelson explains the motivation for can_be_constant_path_p() but I do not understand them.
Definition: value.c:518
entity entity_to_new_value(entity)
Definition: value.c:859
bool entity_has_values_p(entity)
This function could be made more robust by checking the storage of e.
Definition: value.c:911
bool analyzed_type_p(type)
The type t is one of the analyzed types.
Definition: value.c:367
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
Pvecteur vect_dup(Pvecteur v_in)
Pvecteur vect_dup(Pvecteur v_in): duplication du vecteur v_in; allocation de et copie dans v_out;.
Definition: alloc.c:51
Pvecteur vect_make_1D(Value a, Variable x, Value b)
Generate a sparse vector a x + b TCST.
Definition: alloc.c:226
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