PIPS
pointer_values_operators.c
Go to the documentation of this file.
1 /*
2 
3  $Id: pointer_values_operators.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6  Copyright 2010 HPC Project
7 
8  This file is part of PIPS.
9 
10  PIPS is free software: you can redistribute it and/or modify it
11  under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  any later version.
14 
15  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
16  WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  FITNESS FOR A PARTICULAR PURPOSE.
18 
19  See the GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
23 */
24 
25 #ifdef HAVE_CONFIG_H
26  #include "pips_config.h"
27 #endif
28 
29 #include <stdio.h>
30 #include <string.h>
31 
32 #include "genC.h"
33 #include "linear.h"
34 #include "ri.h"
35 #include "ri-util.h"
36 #include "prettyprint.h" // for debugging
37 #include "effects.h"
38 #include "effects-util.h"
39 #include "text-util.h"
40 #include "effects-simple.h"
41 #include "effects-generic.h"
42 #include "misc.h"
43 
44 #include "pointer_values.h"
45 
46 
47 /*
48  @brief makes a pointer value cell_relation from the two input effects; the interpretation
49  of the second effect cell is given by ci. The cells and potential descriptors are copied
50  so that no sharing is introduced.
51  @param lhs_eff effect gives the first cell of the returned pointer value cell_relation
52  @param rhs_eff effect gives the second cell of the returned pointer value cell_relation
53  @param ci gives the interpretation of rhs_eff cell in the returned cell_relation (either value_of or address_of).
54 
55  @return a cell_relation representing a pointer value relation.
56  */
58 {
59  cell_relation pv;
60  list l_pv = NIL;
61 
62  pips_debug(1,"begin for %s cell_interpretation and effects :\n", cell_interpretation_value_of_p(ci)? "value_of" : "address_of");
63  pips_debug_effect(2, "lhs_eff:", lhs_eff);
64  pips_debug_effect(2, "rhs_eff:", rhs_eff);
65 
66  tag lhs_t = effect_approximation_tag(lhs_eff);
67  tag rhs_t = effect_approximation_tag(rhs_eff);
68  tag t = approximation_and(lhs_t, rhs_t);
69 
70  pips_debug(5,"approximation before converting to store independent cells: %s\n",
71  t == is_approximation_exact ? "must": "may");
72 
74 
76 
77  cell rhs_c = effect_cell(rhs_eff);
78  bool changed_rhs_p = false;
79  bool changed_lhs_p = false;
80 
83  else
84  {
86  lhs_c = simple_cell_to_store_independent_cell(lhs_c, &changed_lhs_p);
87  rhs_c = simple_cell_to_store_independent_cell(rhs_c, &changed_rhs_p);
88  }
89 
90  if (changed_lhs_p || changed_rhs_p)
91  {
92  pips_debug(5, "approximation set to may after change to store independent cell\n");
94  }
95 
97  pv = make_value_of_pointer_value(lhs_c,
98  rhs_c,
99  t,
101  else
103  rhs_c,
104  t,
106 
107  bool exact_preceding_p;
111  true,
112  & exact_preceding_p))
113  {
114  list l_remnants = NIL;
115  cell_relation exact_old_pv = cell_relation_undefined;
116  list l_old_values = NIL;
117 
118  pips_debug(4, "lhs path is a predecessor of rhs path, looking for an exact old value for rhs_eff\n");
119 
120  l_old_values = effect_find_equivalent_pointer_values(lhs_eff, l_in,
121  &exact_old_pv,
122  &l_remnants);
123  gen_free_list(l_remnants);
124  if (!cell_relation_undefined_p(exact_old_pv))
125  {
126  cell_relation new_pv = simple_pv_translate(pv, false, exact_old_pv);
127  l_pv = CONS(CELL_RELATION, new_pv, l_pv);
128  }
129  else
130  {
131  FOREACH(CELL_RELATION, old_pv, l_old_values) {
132  cell_relation new_pv = simple_pv_translate(pv, false, old_pv);
133  l_pv = CONS(CELL_RELATION, new_pv, l_pv);
134  }
135  }
136  free_cell_relation(pv);
137  gen_free_list(l_old_values);
138  }
139  else
140  l_pv = CONS(CELL_RELATION, pv, l_pv);
141 
142  pips_debug_pvs(2, "generating:", l_pv);
143  pips_debug(1,"end\n");
144  return l_pv;
145 }
146 
147 /**
148  @brief eliminate the cells of l_kill from l_in
149  @param l_kill is the list of effects describing the cells to eliminated from l_in
150  @param l_in is the input list of pointer_values.
151  @param ctxt is a pointer on the pointer values analysis contex.
152 
153  @return a list of newly allocated pointer_values
154  */
155 list kill_pointer_values(list /* of cell_relations */ l_in,
156  list /* of effects */ l_kill,
157  pv_context * ctxt)
158 {
159  list l_res = NIL;
160  pips_debug_pvs(5, "l_in =", l_in);
161  pips_debug_effects(5, "l_kill =", l_kill);
162 
163  if (ENDP(l_kill))
164  {
165  l_res = gen_full_copy_list(l_in);
166  }
167  else
168  {
169  l_res = l_in;
170  FOREACH(EFFECT, eff_kill, l_kill)
171  {
172  list l_cur = kill_pointer_value(eff_kill, l_res, ctxt);
173  if (l_res != l_in) gen_full_free_list(l_res);
174  l_res = l_cur;
175  }
176  }
177 
178  pips_debug_pvs(5, "returning :", l_res);
179  return l_res;
180 }
181 
182 
183 /**
184  @brief eliminate the cell of eff_kill from l_in
185  @param eff_kill is the effect describing the cell to be killed
186  @param l_in is the input list of pointer_values.
187  @param ctxt is a pointer on the pointer values analysis contex.
188 
189  @return a list of newly allocated pointer_values
190 */
191 /* Not yet very generic: either should be made generic or a specific version made
192  for convex pointer values/effects. */
193 list kill_pointer_value(effect eff_kill, list /* of cell_relations */ l_in,
194  pv_context * ctxt)
195 {
196  list l_out = NIL;
197 
198  pips_debug_pvs(1, "begin with l_in:", l_in);
199  pips_debug_effect(1, "and eff_kill:", eff_kill);
200 
201 
202  if (anywhere_effect_p(eff_kill))
203  {
204  /* all pointers may be killed */
205  pips_debug(5, "anywhere case \n");
206 
207  FOREACH(CELL_RELATION, pv_in, l_in)
208  {
209  cell_relation pv_out = copy_cell_relation(pv_in);
211  l_out = CONS(CELL_RELATION, pv_out, l_out);
212  }
213  }
214  else
215  {
216  /* eff_kill characteristics */
217  cell cell_kill = effect_cell(eff_kill);
218  tag app_kill = effect_approximation_tag(eff_kill);
219  reference ref_kill = effect_any_reference(eff_kill);
220  entity e_kill = reference_variable(ref_kill);
221  list ind_kill = reference_indices(ref_kill);
222  size_t nb_ind_kill = gen_length(ind_kill);
223  /******/
224 
225  /* using old_values, take into account the impact of eff_kill on
226  * l_in pointer values second cells which must be expressed in terms of
227  * unchanged paths.
228  */
229  list l_remnants = NIL;
230  cell_relation exact_old_pv = cell_relation_undefined;
231  list l_old_values = NIL;
232 
233  pips_debug(4, "begin, looking for an exact old value for eff_orig\n");
234 
235  l_old_values = effect_find_equivalent_pointer_values(eff_kill, l_in,
236  &exact_old_pv,
237  &l_remnants);
238  pips_debug_pvs(3, "l_old_values:", l_old_values);
239  pips_debug_pvs(3, "l_remnants:", l_remnants);
240  pips_debug_pv(3, "exact_old_pv:", exact_old_pv);
241 
242  list l_keep = NIL;
243  FOREACH(CELL_RELATION, pv_in, l_remnants)
244  {
245  bool first_p = false; /* should we translate the first or the second pv_in cell */
246  bool to_be_translated = false; /* must it be translated ? */
247  bool exact_preceding_test = true;
248 
249  /* pv_in first cell characteristics */
250  cell cell_in_1 = cell_relation_first_cell(pv_in);
251  reference ref_in_1 = cell_reference(cell_in_1);
252  entity e_in_1 = reference_variable(ref_in_1);
253  list ind_in_1 = reference_indices(ref_in_1);
254  size_t nb_ind_in_1 = gen_length(ind_in_1);
255  /******/
256 
257  /* pv_in second cell characteristics */
258  cell cell_in_2 = cell_relation_second_cell(pv_in);
259  reference ref_in_2 = cell_reference(cell_in_2);
260  entity e_in_2 = reference_variable(ref_in_2);
261  list ind_in_2 = reference_indices(ref_in_2);
262  size_t nb_ind_in_2 = gen_length(ind_in_2);
263  /******/
264 
265  pips_debug_pv(3, "considering pv_in:", pv_in);
266 
267  if (same_entity_p(e_kill, e_in_2) && nb_ind_kill <= nb_ind_in_2)
268  {
269  if (cell_relation_second_address_of_p(pv_in) && nb_ind_kill == nb_ind_in_2)
270  {
271  /* pointer value relation is still valid */
272  pips_debug(3, "address_of case, and nb_ind_in == nb_ind_kill_2\n");
273  to_be_translated = false;
274  }
275  else
276  {
277  pips_debug(3, "second cell is candidate for translation\n");
278  first_p = false;
279  bool inclusion_test_exact_p = false;
280  if ( (nb_ind_kill == nb_ind_in_2 &&
282  cell_kill, descriptor_undefined, &inclusion_test_exact_p))
283  ||
284  (nb_ind_kill < nb_ind_in_2 &&
286  ref_in_2, descriptor_undefined,
288  true,
289  &exact_preceding_test)))
290  to_be_translated = true;
291  else to_be_translated = false;
292  }
293  }
294  else if (same_entity_p(e_kill, e_in_1) && nb_ind_kill <= nb_ind_in_1)
295  {
296  pips_debug(3, "first cell is candidate for translation\n");
297  first_p = true;
298  bool inclusion_test_exact_p = false;
299  if ( (nb_ind_kill == nb_ind_in_1 &&
301  cell_kill, descriptor_undefined,
302  &inclusion_test_exact_p) )
303  ||
304  (nb_ind_kill < nb_ind_in_1 &&
306  ref_in_1, descriptor_undefined,
308  true,
309  &exact_preceding_test)))
310  to_be_translated = true;
311  else to_be_translated = false;
312  }
313  else
314  {
315  to_be_translated = false;
316  }
317 
318  if (to_be_translated)
319  {
320  pips_debug(3, "%s cell must be translated\n", first_p ? "first" : "second");
321 
322  /* This should be made generic */
323 
324  /* we must translate ref_in using the old_values */
325  /* if there is an exact candidate, it is ranked first
326  * and we can use it */
327  if (exact_old_pv != cell_relation_undefined)
328  {
329  cell_relation new_pv = simple_pv_translate(pv_in, first_p, exact_old_pv);
330  pips_debug_pv(3, "translated to:", new_pv);
331  l_out = CONS(CELL_RELATION, new_pv, l_out);
332  }
333  else /* generate a new pv for each element of old_values */
334  {
335  FOREACH(CELL_RELATION, old_pv, l_old_values) {
336  cell_relation new_pv = simple_pv_translate(pv_in, first_p, old_pv);
337  pips_debug_pv(3, "translated to:", new_pv);
338  l_out = CONS(CELL_RELATION, new_pv, l_out);
339  } /* FOREACH(CELL_RELATION, old_pv, l_old_values) */
340  } /* else branch of if (exact_first_pv) */
341  } /* if (to_be_translated) */
342  else
343  {
344  pips_debug(3, "non matching case, keep as is\n");
345  l_keep = CONS(CELL_RELATION, copy_cell_relation(pv_in), l_keep);
346  }
347  } /* FOREACH (CELL_RELATION, pv_in, l_remnants) */
348 
349  list l_tmp = (*ctxt->pvs_must_union_func)(l_out, l_keep);
350  //gen_full_free_list(l_out);
351  //gen_full_free_list(l_keep);
352  l_out = l_tmp;
353 
354  /* Second, take into account the impact of eff_kill on l_old_values relations.
355  * We only have to keep those which are not completely killed by kill_eff, and
356  * set their approximation to may (this is also true for exact_old_pv)
357  */
358 
359  /* first use exact_old_pv to translate exact old_values */
361  if (!cell_relation_undefined_p(exact_old_pv))
362  {
363  pips_debug(3, "handling exact_old_pv\n");
364  reference ref_old =
366  if(same_entity_p(reference_variable(ref_old),e_kill))
367  {
368  pips_debug(3, "exact_old_pv is inverted -> translate\n");
369  tmp_old_pv = make_value_of_pointer_value
370  (copy_cell(cell_relation_second_cell(exact_old_pv)),
371  copy_cell(cell_relation_first_cell(exact_old_pv)),
372  cell_relation_approximation_tag(exact_old_pv),
374  }
375  else
376  {
377  pips_debug(3, "exact_old_pv is not inverted\n");
378  tmp_old_pv = copy_cell_relation(exact_old_pv);
379  }
380  }
381 
382  /* Then the other old_values */
383  pips_debug(3, "dealing with old values\n");
384  FOREACH(CELL_RELATION, pv_old, l_old_values)
385  {
386  pips_debug_pv(3, "dealing with pv_old:", pv_old);
387  /* we already know that there may be a non-empty
388  * intersection with cell_kill */
389  if (app_kill == is_approximation_may)
390  {
391  pips_debug(3, "may kill, just change the approximation\n");
392  cell_relation pv_out = copy_cell_relation(pv_old);
394  l_out = CONS(CELL_RELATION, pv_out, l_out);
395  }
396  else /* some more work is necessary */
397  {
398  cell first_cell_old = cell_relation_first_cell(pv_old);
399  bool exact_inclusion_p = false;
400  bool inclusion_p = simple_cells_inclusion_p(first_cell_old, descriptor_undefined,
401  cell_kill, descriptor_undefined,
402  &exact_inclusion_p);
403 
404  if (inclusion_p && exact_inclusion_p)
405  {
406  pips_debug(3, "first_cell_old exactly included in cell_kill"
407  " -> pv_old is translated or killed\n");
408  if(!cell_relation_undefined_p(tmp_old_pv)
411  || cell_relation_second_address_of_p(tmp_old_pv))))
412  {
413  cell_relation new_pv = simple_pv_translate(tmp_old_pv,
414  true,
415  pv_old);
416  pips_debug_pv(3, "translating to:", new_pv);
417  l_out = CONS(CELL_RELATION, new_pv, l_out);
418  }
419  }
420  else
421  {
422  cell second_cell_old = cell_relation_second_cell(pv_old);
423  bool exact_inclusion_p = false;
424  bool inclusion_p = simple_cells_inclusion_p(second_cell_old, descriptor_undefined,
425  cell_kill, descriptor_undefined,
426  &exact_inclusion_p);
427  if (inclusion_p && exact_inclusion_p)
428  {
429  pips_debug(3, "second_cell_old exactly included in "
430  "cell_kill -> pv_old is translated or killed\n");
431 
432  if(!cell_relation_undefined_p(tmp_old_pv))
433  {
434  cell_relation new_pv = simple_pv_translate(tmp_old_pv,
435  true,
436  pv_old);
437  pips_debug_pv(3, "translating to:", new_pv);
438  l_out = CONS(CELL_RELATION, new_pv, l_out);
439  }
440  }
441  else
442  {
443  pips_debug(3, "may be included case"
444  " -> keep with may approximation\n");
445  /* some more precise work could be done here by
446  * computing the difference between the pv_old
447  * first cell and cell_kill. I don't know if it
448  * would be really useful. So let us avoid too
449  * complex things for the moment.
450  */
451  cell_relation pv_out = copy_cell_relation(pv_old);
454  l_out = CONS(CELL_RELATION, pv_out, l_out);
455  }
456  }
457  }
458  }
459  gen_free_list(l_old_values);
460 
461  pips_debug(3, "dealing with exact_old_pv\n");
462  if (!cell_relation_undefined_p(tmp_old_pv))
463  {
464  cell first_cell_old = cell_relation_first_cell(tmp_old_pv);
465  bool exact_inclusion_p = false;
466  if (app_kill == is_approximation_may)
467  {
468  pips_debug(3,
469  "may kill, keep exact_old_pv with may approximation\n");
470  cell_relation pv_out = copy_cell_relation(exact_old_pv);
472  l_out = CONS(CELL_RELATION, pv_out, l_out);
473  }
474  else if (simple_cells_inclusion_p(first_cell_old, descriptor_undefined,
475  cell_kill, descriptor_undefined,
476  &exact_inclusion_p)
477  && exact_inclusion_p)
478  {
479  pips_debug(3, "first cell of exact_old_pv exactly included in cell_kill "
480  "-> exact_old_pv is killed\n");
481  }
482  else
483  {
484  pips_debug(3, "may be included case"
485  " -> keep with may approximation\n");
486  /* some more precise work could be done here by
487  * computing the difference between the pv_old
488  * first cell and cell_kill. I don't know if it
489  * would be really useful. So let us avoid too
490  * complex things for the moment.
491  */
492  cell_relation pv_out = copy_cell_relation(tmp_old_pv);
495  l_out = CONS(CELL_RELATION, pv_out, l_out);
496  }
497  free_cell_relation(tmp_old_pv);
498  }
499 
500  }
501  pips_debug_pvs(1, "returning:", l_out);
502 
503  return l_out;
504 }
505 
506 /**
507  @param pv_in a the input pointer_value relation
508  @param in_first_p is true (false) if the first (second) cell of pv_in has to be translated
509  @param pv_old is the cell relation that gives the value of a prefix path of the
510  first (second) cell of pv_in
511  @result a newly allocated pointer_value relation in which the first (second) has been translated.
512  */
514 {
515  cell_relation pv_new;
516 
517  pips_debug_pv(5, "pv_in =", pv_in);
518  pips_debug(5, "translating %s cell\n", in_first_p? "first": "second");
519  pips_debug_pv(5, "pv_old =", pv_old);
520 
521  /* pv_in first or second cell characteristics */
522  cell cell_in = in_first_p ? cell_relation_first_cell(pv_in) : cell_relation_second_cell(pv_in);
523  reference ref_in = cell_reference(cell_in);
524  entity e_in = reference_variable(ref_in);
525  list ind_in = reference_indices(ref_in);
526  size_t nb_ind_in = gen_length(ind_in);
527  /******/
528 
529  /* pv_old characteristics */
530  reference ref_old_1 =
532  list ind_old_1 = reference_indices(ref_old_1);
533  size_t nb_ind_old_1 = gen_length(ind_old_1);
534 
535  reference ref_old_2 =
537  list ind_old_2 = reference_indices(ref_old_2);
538  size_t nb_ind_old_2 = gen_length(ind_old_2);
539  bool anywhere_old_p = cell_relation_second_address_of_p(pv_old)
541  /******/
542 
543  bool old_first_p = same_entity_p(reference_variable(ref_old_1), e_in); /* is the first cell of pv_old the prefix of ref_in? */
544 
545  //reference prefix_ref = old_first_p ? ref_old_1 : ref_old_2;
546  reference target_ref = old_first_p ? ref_old_2 : ref_old_1;
547 
548  reference ref;
549  descriptor d;
550  bool exact_translation_p;
551  int nb_common_indices;
552  bool address_of_ref = false;
553 
554  if (old_first_p && anywhere_old_p)
555  {
556  cell c1 = in_first_p ? copy_cell(cell_relation_second_cell(pv_in)) :
559  pv_new = make_address_of_pointer_value(c1, c2,
561  }
562  else
563  {
564  if ( (!old_first_p) && cell_relation_second_address_of_p(pv_old))
565  {
566  /* act as if there were a [0] indice at the end of ref_old_1 */
567  nb_common_indices = (int) nb_ind_old_1 + 1;
568 
570  (ref_in, descriptor_undefined, /* not generic here */
571  target_ref, descriptor_undefined, /* not generic here */
572  nb_common_indices,
573  &ref, &d, &exact_translation_p);
574 
575  }
576  else
577  {
578  nb_common_indices = old_first_p ? (int) nb_ind_old_1 : (int) nb_ind_old_2;
579 
581  {
582  if (nb_ind_in == 0)
583  {
584  ref = copy_reference(target_ref);
585  exact_translation_p = true;
586  address_of_ref = true;
587  }
588  else
590  (ref_in, descriptor_undefined, /* not generic here */
591  target_ref, descriptor_undefined, /* not generic here */
592  nb_common_indices,
593  &ref, &d, &exact_translation_p);
594  }
595  else
597  (ref_in, descriptor_undefined, /* not generic here */
598  target_ref, descriptor_undefined, /* not generic here */
599  nb_common_indices,
600  &ref, &d, &exact_translation_p);
601  }
602  pips_debug(5, "ref after translation %s\n",
604 
605  tag new_t = (cell_relation_may_p(pv_in) || cell_relation_may_p(pv_old) || !exact_translation_p)
607 
608  if (in_first_p)
609  {
611  {
612  if (!address_of_ref)
615  new_t, make_descriptor_none());
616  else
619  new_t, make_descriptor_none());
620  }
621  else
622  {
623  pips_assert("pointer values do not have two address of cells\n", !address_of_ref);
626  new_t, make_descriptor_none());
627  }
628  }
629  else
630  {
631  if(cell_relation_second_value_of_p(pv_in) && !address_of_ref )
634  new_t, make_descriptor_none());
635  else
638  new_t, make_descriptor_none());
639  }
640  }
641  return pv_new;
642 }
643 
644 
645 /**
646  @brief find pointer_values in l_in which give (possible or exact) paths
647  equivalent to eff.
648  @param eff is the considered input path.
649  @param l_in is the input pointer values list.
650  @param exact_aliased_pv gives an exact equivalent path found in l_in if it exists.
651  @param l_in_remnants contains the elemnts of l_in which are neither
652  exact_aliased_pv nor in the returned list.
653 
654  @return a list of elements of l_in which give (possible or exact) paths
655  equivalent to eff, excluding exact_aliased_pv if one exact equivalent
656  path can be found in l_in.
657  */
659  cell_relation * exact_aliased_pv,
660  list * l_in_remnants)
661 {
662  return generic_effect_find_equivalent_simple_pointer_values(eff, l_in, exact_aliased_pv, l_in_remnants,
666 }
667 
668 /**
669  @brief find all paths equivalent to eff cell in l_pv by performing a transitive closure
670  @param eff is the input effect
671  @param l_pv is the list of current pointer_values relations
672  @param ctxt is the pv analysis context
673  @return a list of effects whose cells are equivalent to eff_kill cell according to l_pv.
674  Their approximation does not depend on the approximation of the input effect,
675  but only on the exactness of the finding process.
676 
677  */
679 {
680  bool exact_p;
681  // for gcc
682  pips_assert("true", ctxt==ctxt);
690 }
691 
692 
693 void pointer_values_remove_var(entity e, bool may_p, list l_in,
694  pv_results *pv_res, pv_context *ctxt)
695 {
696  pips_debug(5, "begin for entity %s\n", entity_name(e));
697  pips_debug_pvs(5, "input l_in\n", l_in);
698 
699  /* possibly assign an undefined value to pointers reachable
700  from e without dereferencements) */
702  assignment_to_post_pv(exp, may_p,
704  false, l_in, pv_res, ctxt);
705  l_in = pv_res->l_out;
707 
708  /* Then replace all occurrences of e by an
709  undefined value if it's not a may kill */
710  if (!may_p)
711  {
712  list l_out = NIL;
713  FOREACH(CELL_RELATION, pv, l_in)
714  {
715  pips_debug_pv(5, "considering pv:", pv);
716  cell_relation new_pv = copy_cell_relation(pv);
717  cell c1 = cell_relation_first_cell(new_pv);
719 
720  cell c2 = cell_relation_second_cell(new_pv);
722  bool keep = true;
723 
724  if (same_entity_p(e1, e))
725  {
727  {
728  free_cell(c1);
731  }
732  else
733  keep = false;
734  }
735  else if (same_entity_p(e2, e))
736  {
738  {
739  free_cell(c2);
744  }
745  else keep = false;
746  }
747  if (keep)
748  l_out = CONS(CELL_RELATION, new_pv, l_out);
749  else
750  free_cell_relation(new_pv);
751  }
752  gen_full_free_list(l_in);
753  pv_res->l_out = l_out;
754  }
755  pips_debug_pvs(5, "end with pv_res->l_out = \n", pv_res->l_out );
756 }
757 
758 
759 
760 /*
761  @brief change each element of simple pointer values input list into a store independent pointer value.
762 
763  @param l_pv is the input list of simple pointer values
764  @param t is unused, but is here for homogeneity purposes
765 */
767 {
770 
771  bool b1, b2;
772 
775 
776  if (cell_relation_exact_p(pv) && (b1 || b2))
778  return pv;
779 }
780 
781 /*
782  @brief report the impact of store modification modelized by the input transformer onto the input list of pointer values
783 
784  @param l_pv is the input list of pointer values
785  @param t is the transfomer that modelizes the store modification
786  @param ctxt is a pointer on the pointer value analysis context holder.
787 */
789 {
790  FOREACH(CELL_RELATION, pv, l_pv)
791  {
792  pv = (*ctxt->pv_composition_with_transformer_func)(pv, t);
793  }
794 
795  return l_pv;
796 }
797 
798 
799 
801 {
802  return CONS(CELL_RELATION, cr, NIL);
803 }
804 
806 {
808  return CONS(CELL_RELATION, cr, NIL);
809 }
810 
812 {
813  pips_debug_pv(5, "pv1 =\n", pv1);
814  pips_debug_pv(5, "pv2 =\n", pv2);
815 
816  cell c_first_1 = cell_relation_first_cell(pv1);
817  cell c_second_1 = cell_relation_second_cell(pv1);
818 
819  cell c_first_2 = cell_relation_first_cell(pv2);
820  cell c_second_2 = cell_relation_second_cell(pv2);
821 
823  if (entity_all_locations_p(cell_entity(c_second_1)))
824  {
825  pips_debug(5, "pv1 second cell is anywhere\n");
827  copy_cell(c_second_1),
830  }
831  else if (entity_all_locations_p(cell_entity(c_second_2)))
832  {
833  pips_debug(5, "pv2 second cell is anywhere\n");
835  copy_cell(c_second_2),
838  }
839  else
840  {
841  pips_debug(5, "general case\n");
842  if ((cell_compare(&c_first_1, &c_first_2) == 0
843  && cell_compare(&c_second_1, &c_second_2) == 0)
844  || (cell_compare(&c_first_1, &c_second_2) == 0
845  && cell_compare(&c_second_1, &c_first_2) == 0)
846  )
847  {
848 
851  tag t;
852 
853  if (t1 == t2) t = t1;
854  else t = is_approximation_exact;
855 
856  pv = copy_cell_relation(pv1);
858  }
859  else
860  {
861 
862  // first cells are equal, but not second cells indices
863  // generate a pv with an unbounded dimension wherever dimensions
864  // are not equal
865  pv = copy_cell_relation(pv1);
867 
868  cell c_second_pv = cell_relation_second_cell(pv);
869  list l_ind_c_second_pv = reference_indices(cell_any_reference(c_second_pv));
870  list l_ind_c_second_2 = reference_indices(cell_any_reference(c_second_2));
871 
872  for(; !ENDP(l_ind_c_second_pv); POP(l_ind_c_second_pv), POP(l_ind_c_second_2))
873  {
874  expression ind_pv = EXPRESSION(CAR(l_ind_c_second_pv));
875  expression ind_2 = EXPRESSION(CAR(l_ind_c_second_2));
876 
877  if (!expression_equal_p(ind_pv, ind_2))
878  {
879  EXPRESSION_(CAR(l_ind_c_second_pv)) = make_unbounded_expression();
880  }
881  }
882 
883  }
884  }
885  pips_debug_pv(5, "pv =\n", pv);
886  list l_res = CONS(CELL_RELATION, pv, NIL);
887  pips_debug_pvs(5, "returning:\n", l_res);
888  return l_res;
889 }
890 
892 {
893  cell c_first_1 = cell_relation_first_cell(pv1);
894  cell c_second_1 = cell_relation_second_cell(pv1);
895 
896  cell c_first_2 = cell_relation_first_cell(pv2);
897  cell c_second_2 = cell_relation_second_cell(pv2);
898 
899  cell_relation pv;
900  if (entity_all_locations_p(cell_entity(c_second_1)))
901  {
902  pips_debug(5, "pv1 second cell is anywhere\n");
904  copy_cell(c_second_1),
907  }
908  else if (entity_all_locations_p(cell_entity(c_second_2)))
909  {
910  pips_debug(5, "pv2 second cell is anywhere\n");
912  copy_cell(c_second_2),
915  }
916  else
917  {
918  if ((cell_compare(&c_first_1, &c_first_2) == 0
919  && cell_compare(&c_second_1, &c_second_2) == 0)
920  || (cell_compare(&c_first_1, &c_second_2) == 0
921  && cell_compare(&c_second_1, &c_first_2) == 0)
922  )
923  {
924 
927  tag t;
928 
929  if (t1 == t2) t = t1;
930  else t = is_approximation_may;
931 
932  pv = copy_cell_relation(pv1);
934  }
935  else
936  {
937  // first cells are equal, but not second cells indices
938  // generate a pv with an unbounded dimension wherever dimensions
939  // are not equal
940  pv = copy_cell_relation(pv1);
942 
943  cell c_second_pv = cell_relation_second_cell(pv);
944  list l_ind_c_second_pv = reference_indices(cell_any_reference(c_second_pv));
945  list l_ind_c_second_2 = reference_indices(cell_any_reference(c_second_2));
946 
947  for(; !ENDP(l_ind_c_second_pv); POP(l_ind_c_second_pv), POP(l_ind_c_second_2))
948  {
949  expression ind_pv = EXPRESSION(CAR(l_ind_c_second_pv));
950  expression ind_2 = EXPRESSION(CAR(l_ind_c_second_2));
951 
952  if (!expression_equal_p(ind_pv, ind_2))
953  {
954  EXPRESSION_(CAR(l_ind_c_second_pv)) = make_unbounded_expression();
955  }
956  }
957 
958  }
959  }
960  list l_res = CONS(CELL_RELATION, pv, NIL);
961  pips_debug_pvs(5, "returning:\n", l_res);
962  return l_res;
963 }
964 
966 {
967  bool undef1 = cell_relation_undefined_p(pv1);
968  bool undef2 = cell_relation_undefined_p(pv2);
969 
970  pips_assert("error: there should be no undefined cell_relations in lists\n", !(undef1 && undef2));
971 
972  if (undef1 || undef2) return true;
973  if (pv_cells_mergeable_p(pv1, pv2)) return true;
974 
975 
976  cell c_first_1 = cell_relation_first_cell(pv1);
977  cell c_second_1 = cell_relation_second_cell(pv1);
978 
979  cell c_first_2 = cell_relation_first_cell(pv2);
980  cell c_second_2 = cell_relation_second_cell(pv2);
981 
982  if (entity_all_locations_p(cell_entity(c_second_1))
984  {
985  int n_first_first = cell_compare(&c_first_1, &c_first_2);
986  if (n_first_first == 0) return true;
987  int n_first_second = cell_compare(&c_first_1, &c_second_2);
988  if (n_first_second == 0) return true;
989  }
990  if (entity_all_locations_p(cell_entity(c_second_2))
992  {
993  int n_first_first = cell_compare(&c_first_1, &c_first_2);
994  if (n_first_first == 0) return true;
995  int n_second_first = cell_compare(&c_second_1, &c_first_2);
996  if (n_second_first == 0) return true;
997  }
998 
999  return false;
1000 
1001 }
1002 
1003 
1004 /*
1005  @brief computes the union of two simple pointer_values list
1006  @param l_pv1 is the first list of pointer_values
1007  @param l_pv2 is the second list of pointer_values
1008  @return a new list of pointer values
1009  */
1011 {
1012 
1014  l_pv1,
1015  l_pv2,
1020  return l_res;
1021 }
1022 
1023 /*
1024  @brief computes the may union of two simple pointer_values list
1025  @param l_pv1 is the first list of pointer_values
1026  @param l_pv2 is the second list of pointer_values
1027  @return a new list of pointer values
1028  */
1030 {
1031 
1033  l_pv1,
1034  l_pv2,
1039  return l_res;
1040 }
1041 
1043 {
1044  bool result = true;
1045 
1046  if (gen_length(l_pv1) != gen_length(l_pv2))
1047  result = false;
1048 
1049  if (result)
1050  {
1051  /* first sort lists */
1054 
1055  /* then compare members syntactically */
1056  while(result && !ENDP(l_pv1))
1057  {
1058  cell_relation pv1 = CELL_RELATION(CAR(l_pv1));
1059  cell_relation pv2 = CELL_RELATION(CAR(l_pv2));
1060 
1061  result = pv_cells_syntactically_equal_p(pv1, pv2);
1062  POP(l_pv1);
1063  POP(l_pv2);
1064  }
1065  }
1066  return result;
1067 }
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
cell make_cell_reference(reference _field_)
Definition: effects.c:293
void free_cell_relation(cell_relation p)
Definition: effects.c:308
cell make_cell(enum cell_utype tag, void *val)
Definition: effects.c:290
void free_cell(cell p)
Definition: effects.c:249
cell_relation copy_cell_relation(cell_relation p)
CELL_RELATION.
Definition: effects.c:305
descriptor make_descriptor_none(void)
Definition: effects.c:442
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
void free_expression(expression p)
Definition: ri.c:853
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
bool entity_all_locations_p(entity e)
test if an entity is the top of the lattice
void const char const char const int
list cell_relations_generic_binary_op(list l1, list l2, bool(*cr1_cr2_combinable_p)(cell_relation, cell_relation), list(*cr1_cr2_binary_op)(cell_relation, cell_relation), list(*cr1_unary_op)(cell_relation), list(*cr2_unary_op)(cell_relation), list(*union_op)(list, list))
functions specific to cell_relations
int cell_compare(cell *c1, cell *c2)
Definition: compare.c:168
int pointer_value_compare(cell_relation *ppv1, cell_relation *ppv2)
Compares two pointer values for sorting.
Definition: compare.c:255
#define pips_debug_effects(level, message, l_eff)
#define pips_debug_effect(level, message, eff)
for debug
list generic_effect_find_aliases_with_simple_pointer_values(effect, list, bool *, transformer, bool(*)(cell, descriptor, cell, descriptor, transformer, bool, bool *), void(*)(cell, descriptor, cell, descriptor, int, cell *, descriptor *, bool *), void(*)(cell, descriptor, cell, descriptor, int, cell *, descriptor *, bool *), bool(*)(cell, descriptor, cell, descriptor, bool *), bool(*)(cell, descriptor, cell, descriptor, bool *), void(*)(cell, cell *, descriptor *))
Definition: eval.c:673
list generic_effect_find_equivalent_simple_pointer_values(effect, list, cell_relation *, list *, bool(*)(cell, descriptor, cell, descriptor, bool *), bool(*)(cell, descriptor, cell, descriptor, bool *), void(*)(cell, cell *, descriptor *))
find pointer_values in l_in which give (possible or exact) paths equivalent to eff.
Definition: eval.c:506
bool simple_cells_inclusion_p(cell c1, __attribute__((__unused__)) descriptor d1, cell c2, __attribute__((__unused__)) descriptor d2, bool *exact_p)
Inclusion test :
bool simple_cells_intersection_p(cell c1, descriptor __attribute__((__unused__)) d1, cell c2, descriptor __attribute__((__unused__)) d2, bool *exact_p)
void simple_cell_reference_with_address_of_cell_reference_translation(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
bool simple_cell_reference_preceding_p(reference, descriptor, reference, descriptor, transformer, bool, bool *)
eval.c
bool simple_cell_preceding_p(cell, descriptor, cell, descriptor, transformer, bool, bool *)
Definition: eval.c:119
void simple_cell_with_value_of_cell_translation(cell, descriptor, cell, descriptor, int, cell *, descriptor *, bool *)
cell simple_cell_to_store_independent_cell(cell, bool *)
void simple_cell_to_simple_cell_conversion(cell, cell *, descriptor *)
Definition: eval.c:154
void simple_cell_reference_with_value_of_cell_reference_translation(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
void simple_cell_with_address_of_cell_translation(cell, descriptor, cell, descriptor, int, cell *, descriptor *, bool *)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define cell_relation_approximation_tag(cr)
#define pips_debug_pv(level, message, pv)
#define effect_approximation_tag(eff)
#define cell_relation_may_p(cr)
#define cell_relation_second_cell(cr)
#define cell_relation_second_interpretation_tag(cr)
#define pips_debug_pvs(level, message, l_pv)
#define cell_relation_exact_p(cr)
#define cell_relation_second_address_of_p(cr)
#define cell_relation_second_value_of_p(cr)
#define cell_relation_first_cell(cr)
bool undefined_pointer_value_cell_p(cell)
bool pv_cells_syntactically_equal_p(cell_relation, cell_relation)
tag approximation_and(tag, tag)
tag approximation_and(tag t1, tag t2) input : two approximation tags.
Definition: effects.c:1198
bool pv_cells_mergeable_p(cell_relation, cell_relation)
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
bool abstract_pointer_value_cell_p(cell)
cell_relation make_address_of_pointer_value(cell, cell, tag, descriptor)
cell_relation make_value_of_pointer_value(cell, cell, tag, descriptor)
bool anywhere_effect_p(effect)
Is it an anywhere effect? ANYMMODULE:ANYWHERE
Definition: effects.c:346
cell make_undefined_pointer_value_cell(void)
entity cell_entity(cell)
Definition: effects.c:57
#define cell_reference(x)
Definition: effects.h:469
#define CELL_RELATION(x)
CELL_RELATION.
Definition: effects.h:479
@ is_cell_interpretation_value_of
Definition: effects.h:396
#define cell_relation_undefined
Definition: effects.h:485
@ is_cell_reference
Definition: effects.h:445
#define cell_interpretation_value_of_p(x)
Definition: effects.h:415
#define descriptor_undefined
Definition: effects.h:559
@ is_approximation_may
Definition: effects.h:341
@ is_approximation_exact
Definition: effects.h:343
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#define effect_cell(x)
Definition: effects.h:640
#define cell_relation_undefined_p(x)
Definition: effects.h:486
void gen_full_free_list(list l)
Definition: genClib.c:1023
#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
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
void gen_sort_list(list l, gen_cmp_func_t compare)
Sorts a list of gen_chunks in place, to avoid allocations...
Definition: list.c:796
#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_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
int tag
TAG.
Definition: newgen_types.h:92
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
void assignment_to_post_pv(expression, bool, expression, bool, list, pv_results *, pv_context *)
list make_simple_pv_from_simple_effects(effect lhs_eff, effect rhs_eff, cell_interpretation ci, list l_in)
pointer_values_operators.c
list simple_pvs_may_union(list l_pv1, list l_pv2)
bool pvs_union_combinable_p(cell_relation pv1, cell_relation pv2)
list simple_pv_may_union(cell_relation pv1, cell_relation pv2)
list pvs_composition_with_transformer(list l_pv, transformer t, pv_context *ctxt)
list simple_pv_must_union(cell_relation pv1, cell_relation pv2)
list kill_pointer_value(effect eff_kill, list l_in, pv_context *ctxt)
eliminate the cell of eff_kill from l_in
list effect_find_aliased_paths_with_pointer_values(effect eff, list l_pv, pv_context *ctxt)
find all paths equivalent to eff cell in l_pv by performing a transitive closure
cell_relation simple_pv_translate(cell_relation pv_in, bool in_first_p, cell_relation pv_old)
list cell_relation_to_list(cell_relation cr)
list simple_pvs_must_union(list l_pv1, list l_pv2)
bool simple_pvs_syntactically_equal_p(list l_pv1, list l_pv2)
list cell_relation_to_may_list(cell_relation cr)
list effect_find_equivalent_pointer_values(effect eff, list l_in, cell_relation *exact_aliased_pv, list *l_in_remnants)
find pointer_values in l_in which give (possible or exact) paths equivalent to eff.
list kill_pointer_values(list l_in, list l_kill, pv_context *ctxt)
eliminate the cells of l_kill from l_in
cell_relation simple_pv_composition_with_transformer(cell_relation pv, transformer __attribute__((unused)) t)
void pointer_values_remove_var(entity e, bool may_p, list l_in, pv_results *pv_res, pv_context *ctxt)
string reference_to_string(reference r)
Definition: expression.c:87
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
expression make_unbounded_expression()
Definition: expression.c:4339
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
#define transformer_undefined
Definition: ri.h:2847
#define EXPRESSION_(x)
Definition: ri.h:1220
#define reference_variable(x)
Definition: ri.h:2326
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define reference_indices(x)
Definition: ri.h:2328
Value b2
Definition: sc_gram.c:105
Value b1
booleen indiquant quel membre est en cours d'analyse
Definition: sc_gram.c:105
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
pv_context is a structure holding the methods to use during pointer values analyses
list(* pvs_must_union_func)(list, list)
BINARY OPERATORS.
cell_relation(* pv_composition_with_transformer_func)(cell_relation, transformer)
UNARY OPERATORS.
pv_results is a structure holding the different results of an expression pointer values analysis
@ keep
bj > b1 -> h1/hj = h1
Definition: union-local.h:61
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207