PIPS
liveness_analysis_engine.c
Go to the documentation of this file.
1 /*
2  $Id: liveness_analysis_engine.c 23375 2017-05-11 08:58:06Z ancourt $
3 
4  Copyright 1989-2016 MINES ParisTech
5  Copyright 2011 HPC Project
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  * This File contains the generic functions necessary for the computation of
29  * live paths analyzes. Beatrice Creusillet.
30  *
31  */
32 
33 #include <stdio.h>
34 #include <string.h>
35 
36 #include "genC.h"
37 
38 #include "linear.h"
39 #include "ri.h"
40 #include "effects.h"
41 #include "database.h"
42 
43 #include "misc.h"
44 #include "ri-util.h"
45 #include "effects-util.h"
46 #include "constants.h"
47 #include "misc.h"
48 #include "text-util.h"
49 #include "text.h"
50 
51 #include "properties.h"
52 
53 #include "pipsdbm.h"
54 #include "resources.h"
55 
56 #include "pointer_values.h"
57 #include "effects-generic.h"
58 #include "prettyprint.h"
59 
60 typedef struct {
65 
66 
68  effects_representation_val representation)
69 {
70  ctxt->memory_effects_only = get_bool_property("MEMORY_EFFECTS_ONLY");
71  ctxt->memory_in_out_effects_only = get_bool_property("MEMORY_IN_OUT_EFFECTS_ONLY");
72  if (! ctxt->memory_effects_only)
73  // if the MEMORY_EFFECTS_ONLY is FALSE on input,
74  // we have to temporarily set MEMORY_EFFECTS_ONLY to
75  // TRUE so that functions computing R/W effects
76  // do not compute non memory effects which would have to be filtered.
77  set_bool_property("MEMORY_EFFECTS_ONLY", true);
78  ctxt->representation = representation;
79 }
80 
82 {
83  if (! ctxt->memory_effects_only
85  // if the MEMORY_EFFECTS_ONLY is FALSE on input, and
86  // we did not want to compute IN non-memory effects,
87  // we have to reset MEMORY_EFFECTS_ONLY to FALSE.
88  set_bool_property("MEMORY_EFFECTS_ONLY", false);
89 }
90 
91 
93 {
94  if (!ctxt->memory_effects_only)
95  lrw = effects_store_effects(lrw);
96 
97  return lrw;
98 }
99 
100 
102 {
103  if (!ctxt->memory_effects_only)
104  gen_free_list(*lrw);
105  *lrw = NIL;
106 }
107 
109 {
110  if (!ctxt->memory_effects_only
111  && !ctxt->memory_in_out_effects_only)
112  lin = effects_store_effects(lin);
113 
114  return lin;
115 }
116 
117 
119 {
120  if (!ctxt->memory_effects_only
121  && !ctxt->memory_in_out_effects_only)
122  gen_free_list(*lin);
123  *lin = NIL;
124 }
125 
126 
127 
128 /**************************** GENERIC INTERPROCEDURAL LIVE_IN PATHS ANALYSIS */
129 
131 {
132  list l_glob = NIL, l_loc = NIL;
133  statement module_stat;
134 
137  db_get_memory_resource(DBR_CODE, module_name, true) );
138  module_stat = get_current_module_statement();
139 
140  // functions that can be pointed by effects_computation_init_func:
141  // effects_computation_no_init
142  // init_convex_in_out_regions
143  // init_convex_rw_regions
144  (*effects_computation_init_func)(module_name);
145 
147 
148  l_loc = load_live_in_paths_list(module_stat);
149 
150  // functions that can be pointed by effects_local_to_global_translation_op:
151  // effects_dynamic_elim
152  // regions_dynamic_elim
153  l_glob = (*effects_local_to_global_translation_op)(l_loc);
154 
155  (*db_put_live_in_summary_paths_func)(module_name, l_glob);
156 
160 
161  // functions that can be pointed by effects_computation_reset_func:
162  // effects_computation_no_reset
163  // reset_convex_in_out_regions
164  // reset_convex_rw_regions
165  (*effects_computation_reset_func)(module_name);
166 
167  return true;
168 }
169 
170 /**************************** GENERIC INTERPROCEDURAL LIVE_OUT PATHS ANALYSIS */
171 
172 typedef struct {
176 
177 static void
179 {
180  ctxt->current_callee = callee;
182 }
183 
184 static void
186 {
189 }
190 
191 static void
193 {
194  pips_debug_effects(3, "adding paths\n", l_paths);
196  ctxt->l_current_paths = l_paths;
197  else
198  // functions that can be pointed by effects_test_union_op:
199  // EffectsMayUnion
200  // RegionsMayUnion
201  // ReferenceTestUnion
202  ctxt->l_current_paths = (*effects_test_union_op)(ctxt->l_current_paths , l_paths,
204 
205  pips_debug_effects(3, "current paths\n", ctxt->l_current_paths);
206 }
207 
208 static bool
210 {
211  pips_debug(1, "considering call to %s\n", entity_name(call_function(c)));
212  pips_debug(2, "current context callee: %s\n", entity_name(ctxt->current_callee));
213 
214  if (call_function(c) != ctxt->current_callee)
215  {
216  return (true);
217  }
218  pips_debug(1, "good candidate\n");
219 
221 
222  /* there is a problem here because the context is in the store preceding the statement
223  * whereas live_out_paths hold after the statement.
224  * So I think I must apply the transformer to get the post-condition.
225  * That's ok for simple paths since they are store independent. BC.
226  */
227  transformer stmt_context = (*load_context_func)(current_stmt);
228 
229  /* There may also be a problem here in C, because calls may be
230  * anywhere inside an expression, and not solely as standalone
231  * statements. It may be better to call this function during the
232  * intraprocedural analysis of callers and not during a standalone
233  * phase which would have to deal with calls in sub-expressions,
234  * and thus also with store/pointers modifications.
235  * BC.
236  */
238 
239  pips_debug_effects(3, "current statement live_out_paths:\n", l_out);
241  call_arguments(c), l_out,
242  stmt_context);
244  return true;
245 }
246 
247 static bool
250 {
251  pips_debug(1, "statement %03zd\n", statement_number(s));
252  return(true);
253 }
254 
255 static void
258 {
259  const char *caller_name;
260  statement caller_statement;
261 
264  caller_name = module_local_name(caller);
265  pips_debug(2, "begin for caller: %s, and callee: %s\n", caller_name,
267  pips_debug(2, "current context callee: %s\n", entity_name(ctxt->current_callee));
268  /* All we need to perform the translation */
270  db_get_memory_resource(DBR_CODE, caller_name, true) );
271  caller_statement = get_current_module_statement();
272 
273  // functions that can be pointed by effects_computation_init_func:
274  // effects_computation_no_init
275  // init_convex_in_out_regions
276  // init_convex_rw_regions
277  (*effects_computation_init_func)(caller_name);
278 
280 
281  make_statement_global_stack(); // in case the semantics library is used
282 
283  //ctxt->current_callee = callee;
284  gen_context_multi_recurse(caller_statement, ctxt,
287  NULL);
288 
289  free_statement_global_stack(); // in case the semantics library is used
290 
295 
296  // functions that can be pointed by effects_computation_reset_func:
297  // effects_computation_no_reset
298  // reset_convex_in_out_regions
299  // reset_convex_rw_regions
300  (*effects_computation_reset_func)(caller_name);
301 }
302 
303 
305 {
306  /* Look for all call sites in the callers */
307  callees callers = (callees) db_get_memory_resource(DBR_CALLERS,
308  module_name,
309  true);
311 
314 
315  ifdebug(1)
316  {
317  pips_debug(1, "begin for %s with %td callers\n",
318  module_name,
319  gen_length(callees_callees(callers)));
321  {fprintf(stderr, "%s, ", caller_name);}
322  fprintf(stderr, "\n");
323  }
324 
327  debug_on("LIVE_PATHS_DEBUG_LEVEL");
329  {
332  }
333  debug_off();
335  ctxt.l_current_paths = NIL;
336  (*db_put_live_out_summary_paths_func)(module_name, ctxt.l_current_paths);
337 
338  ifdebug(1)
339  {
341  db_get_memory_resource(DBR_CODE,
343  true) );
344 
345  pips_debug(1, "live out paths for module %s:\n", module_name);
346  (*effects_prettyprint_func)(ctxt.l_current_paths);
347  pips_debug(1, "end\n");
349  }
350 
354 
355  return true;
356 }
357 
358 /**************** GENERIC INTRAPROCEDURAL LIVE_IN AND LIVE_OUT PATHS ANALYSIS */
359 
360 static void
363 {
364  /* live in paths may have already been computed,
365  * for instance for sequences
366  */
367  pips_debug(1,"begin for statement with ordering: %03zd and number: %03zd\n",
369 
370  if ( !bound_live_in_paths_p(s) )
371  {
372  pips_debug(1, "not bound\n");
373  /* First, we get the live out paths of the statement */
374  list l_live_out = effects_dup(load_live_out_paths_list(s));
375 
376  /* Live_in(S) = (live_out(S) o T(S) - W(S)) U IN (S) */
377 
378  /* first take care of declarations */
381  {
383  storage decl_storage = entity_storage(decl);
384  if (storage_ram_p(decl_storage)
385  // keep paths on static variables
386  && !static_area_p(ram_section(storage_ram(decl_storage))))
387  l_live_out = filter_effects_with_declaration(l_live_out, decl);
388  }
389  }
390 
391  // then move the live_out effects of the statement in the store
392  // before the statement
393  transformer t = (*load_completed_transformer_func)(s);
394 
395  // functions that can be pointed by effects_transformer_composition_op:
396  // effects_composition_with_transformer_nop
397  // effects_undefined_composition_with_transformer
398  // convex_regions_transformer_compose
399  // simple_effects_composition_with_effect_transformer
400  (*effects_transformer_composition_op)(l_live_out, t);
401 
402  // next, remove the effects written by the statement
403  // and add the in effects of the statement
405  list l_write = effects_write_effects_dup(l_rw);
406  pips_debug_effects(5, "write effects:\n", l_write);
407 
409  pips_debug_effects(5, "in effects:\n", l_in);
410 
411  // functions that can be pointed by effects_union_op:
412  // ProperEffectsMustUnion
413  // RegionsMustUnion
414  // ReferenceUnion
415  // EffectsMustUnion
416  // functions that can be pointed by effects_sup_difference_op:
417  // effects_undefined_binary_operator
418  // RegionsSupDifference
419  // EffectsSupDifference
420  list l_live_in = (*effects_union_op)(
421  effects_dup(l_in),
422  (*effects_sup_difference_op)(l_live_out, l_write,
425  pips_debug_effects(5, "resulting live in paths:\n", l_live_in);
426 
427 
428  store_live_in_paths_list(s, l_live_in);
429 
430  reset_converted_rw_effects(&l_rw, ctxt);
431  reset_converted_in_effects(&l_in, ctxt);
432 
433  }
434  pips_debug(1,"end\n");
435  return;
436 }
437 
438 static bool
441 {
442  pips_debug(1,"begin\n");
443 
444  /* Adopt a very conservative strategy:
445  * live_out(node)= live_out(unstructured)*may U (U_{n \in nodes} IN(nodes))
446  * If convex paths were to be computed, transformers should be taken into account.
447  */
448  /* The exit node is a particular case: its live_out paths are the live_out paths
449  * of the unstructured.
450  */
451 
452  statement
454  control exit_ctrl = unstructured_exit( unstr );
455  statement exit_node = control_statement(exit_ctrl);
456 
458  pips_debug_effects(3, "live out paths of whole unstructured:\n", l_live_out_unstr);
459  store_live_out_paths_list(exit_node, l_live_out_unstr);
460 
461  if(control_predecessors(exit_ctrl) == NIL && control_successors(exit_ctrl) == NIL)
462  {
463  /* there is only one statement in u; */
464  pips_debug(6, "unique node\n");
465  }
466  else
467  {
468  l_live_out_unstr = effects_dup(l_live_out_unstr);
469  effects_to_may_effects(l_live_out_unstr); /* It may be executed... */
470 
471  list l_in = NIL;
472 
473  list l_nodes = NIL;
475  (ctrl, unstr, l_nodes,
476  {
477  statement node_stmt = control_statement(ctrl);
478  pips_debug(3, "visiting node statement with ordering: "
479  "%03zd and number: %03zd\n",
480  statement_ordering(node_stmt),
481  statement_number(node_stmt));
482 
483  list l_in_node = convert_in_effects(load_in_effects_list(node_stmt), ctxt);
484  list l_in_node_may = effects_dup(l_in_node);
485  effects_to_may_effects(l_in_node_may);
486 
487  // functions that can be pointed by effects_union_op:
488  // ProperEffectsMustUnion
489  // RegionsMustUnion
490  // ReferenceUnion
491  // EffectsMustUnion
492  l_in = (*effects_union_op)(l_in_node_may, l_in,
494  pips_debug_effects(5, "current in effects:\n", l_in);
495  reset_converted_in_effects(&l_in_node, ctxt);
496  });
497 
498  // functions that can be pointed by effects_union_op:
499  // ProperEffectsMustUnion
500  // RegionsMustUnion
501  // ReferenceUnion
502  // EffectsMustUnion
503  list l_live_out_nodes = (*effects_union_op)(l_in, l_live_out_unstr,
505  pips_debug_effects(3, "l_live_out_nodes:\n", l_live_out_nodes);
506 
507  FOREACH(CONTROL, ctrl, l_nodes)
508  {
509 
510  statement node_stmt = control_statement(ctrl);
511 
512  /* be sure live_out paths are not stored twice, in particular
513  for the exit node
514  */
515  if ( !bound_live_out_paths_p(node_stmt) )
516  {
517  pips_debug(3, "storing live out paths for node statement "
518  "with ordering: %03zd and number: %03zd\n",
519  statement_ordering(node_stmt),
520  statement_number(node_stmt));
521  store_live_out_paths_list(node_stmt, effects_dup(l_live_out_nodes));
522  }
523  }
524  }
525 
526  pips_debug(1,"end\n");
527 
528  return true;
529 }
530 
531 static bool
534 {
535  statement
537  statement body = forloop_body(l);
538 
539  pips_debug(1,"begin\n");
540 
541  /* The live out paths of an iteration are the paths that
542  * - belong to the live in paths of the next iteration if it exists,
543  * that is to say if the condition evaluates to true;
544  * the write effects of the condition evaluation mask the
545  * live in paths of the next iteration; and the in effects
546  * of the condition evaluation must be added.
547  * - or belong to the live out of the whole loop if the next iteration
548  * does not exist. However, the condition is evaluated,
549  * and its write effects mask the live out paths at the end of the
550  * whole loop.
551  */
552 
553  /* First, we get the live out paths of the whole loop
554  */
556  pips_debug_effects(3, "live out paths of whole loop:\n", l_live_out_loop);
557  effects_to_may_effects(l_live_out_loop); /* It may be executed... */
558 
559  /* ...or another next iteration of the loop body */
560  list l_in_next_iter = convert_in_effects(load_invariant_in_effects_list(body), ctxt);
561  list l_in_next_iter_may = effects_dup(l_in_next_iter);
562  effects_to_may_effects(l_in_next_iter_may);
563  pips_debug_effects(3, "(may) in effects of next iterations:\n",
564  l_in_next_iter_may);
565  reset_converted_in_effects(&l_in_next_iter, ctxt);
566 
567  // functions that can be pointed by effects_union_op:
568  // ProperEffectsMustUnion
569  // RegionsMustUnion
570  // ReferenceUnion
571  // EffectsMustUnion
572  list l_live_out_after_cond =
573  (*effects_union_op)(l_live_out_loop,
574  l_in_next_iter_may,
576 
577  pips_debug_effects(3, "live out paths after header evaluation:\n",
578  l_live_out_after_cond);
579 
580  /* Take into account the effects of the header */
582  ctxt);
583 
584  list l_write_cond =
586  pips_debug_effects(3, "write effects of condition:\n", l_write_cond);
587 
588 
589  /* We don't have the in effects of the header evaluation
590  * we safely approximate them by its may read proper effects
591  * if there are write effects during its evaluation
592  * We could be much more precise here by distinguishing
593  * the three different components and re-computing their effects.
594  * However, for loops are generally converted to loops or while loops
595  * by the controlizer, so I leave this as it is for the time being.
596  */
597  list l_in_cond =
599  if (!ENDP(l_write_cond)) effects_to_may_effects(l_in_cond);
600  pips_debug_effects(3, "approximation of in effects of condition:\n", l_in_cond);
601 
602  // functions that can be pointed by effects_union_op:
603  // ProperEffectsMustUnion
604  // RegionsMustUnion
605  // ReferenceUnion
606  // EffectsMustUnion
607  // functions that can be pointed by effects_sup_difference_op:
608  // effects_undefined_binary_operator
609  // RegionsSupDifference
610  // EffectsSupDifference
611  list l_live_out_body =
612  (*effects_union_op)(l_in_cond,
613  (*effects_sup_difference_op)(l_live_out_after_cond,
614  l_write_cond,
617 
618 
619  reset_converted_rw_effects(&l_prop_cond, ctxt);
620 
621  pips_debug_effects(3, "live out paths of loop body:\n", l_live_out_body);
622 
623  store_live_out_paths_list(body, l_live_out_body);
624 
625  pips_debug(1,"end\n");
626 
627  return true;
628 }
629 
630 static bool
632 {
633  statement
635  statement body = whileloop_body(l);
636 
637  pips_debug(1,"begin\n");
638 
639  /* The live out paths of an iteration are the paths that
640  * - belong to the live in paths of the next iteration if it exists,
641  * that is to say if the condition evaluates to true;
642  * the write effects of the condition evaluation mask the
643  * live in paths of the next iteration; and the in effects
644  * of the condition evaluation must be added.
645  * - or belong to the live out of the whole loop if the next iteration
646  * does not exist. However, the condition is evaluated,
647  * and its write effects mask the live out paths at the end of the
648  * whole loop.
649  */
650 
651  /* First, we get the live out paths of the whole loop
652  */
654  pips_debug_effects(3, "live out paths of whole loop:\n", l_live_out_loop);
655  effects_to_may_effects(l_live_out_loop); /* It may be executed... */
656 
657  /* ...or another next iteration of the loop body */
658  list l_in_next_iter = convert_in_effects(load_invariant_in_effects_list(body), ctxt);
659  list l_in_next_iter_may = effects_dup(l_in_next_iter);
660  effects_to_may_effects(l_in_next_iter_may);
661  pips_debug_effects(3, "(may) in effects of next iterations:\n",
662  l_in_next_iter_may);
663  reset_converted_in_effects(&l_in_next_iter, ctxt);
664 
665  // functions that can be pointed by effects_union_op:
666  // ProperEffectsMustUnion
667  // RegionsMustUnion
668  // ReferenceUnion
669  // EffectsMustUnion
670  list l_live_out_after_cond =
671  (*effects_union_op)(l_live_out_loop,
672  l_in_next_iter_may,
674 
675  pips_debug_effects(3, "live out paths after any condition evaluation:\n",
676  l_live_out_after_cond);
677 
678  /* Take into account the effects of the condition */
680  ctxt);
681 
682  list l_write_cond =
684  pips_debug_effects(3, "write effects of condition:\n", l_write_cond);
685 
686 
687  /* We don't have the in effects of the condition evaluation
688  * we safely approximate them by its may read proper effects
689  * if there are write effects during its evaluation
690  */
691  list l_in_cond =
693  if (!ENDP(l_write_cond)) effects_to_may_effects(l_in_cond);
694  pips_debug_effects(3, "approximation of in effects of condition:\n", l_in_cond);
695 
696  // functions that can be pointed by effects_union_op:
697  // ProperEffectsMustUnion
698  // RegionsMustUnion
699  // ReferenceUnion
700  // EffectsMustUnion
701  // functions that can be pointed by effects_sup_difference_op:
702  // effects_undefined_binary_operator
703  // RegionsSupDifference
704  // EffectsSupDifference
705  list l_live_out_body =
706  (*effects_union_op)(l_in_cond,
707  (*effects_sup_difference_op)(l_live_out_after_cond,
708  l_write_cond,
711 
712 
713  reset_converted_rw_effects(&l_prop_cond, ctxt);
714 
715  pips_debug_effects(3, "live out paths of loop body:\n", l_live_out_body);
716 
717  store_live_out_paths_list(body, l_live_out_body);
718 
719  pips_debug(1,"end\n");
720 
721  return true;
722 }
723 
724 static void
726 {
727  statement
729  bool before_p = evaluation_before_p(whileloop_evaluation(l));
730  statement body = whileloop_body(l);
731 
732  list l_live_in_loop = NIL;
733 
734  pips_debug(1,"begin\n");
735 
736  /* If the loop belongs to a sequence of statements, which is
737  * generally the case, its live in paths have already been computed.
738  * I don't yet know if they may be much more precisely computed here.
739  * For performance reasons, I don't try to recompute them if they
740  * are already available.
741  * see also the comment inside the else branch of if (!before_p)
742  * about the way of computing live in paths.
743  * The code below is likely to be seldom executed;
744  * however, it has been tested on small cases.
745  */
747  {
748  list l_live_in_body = effects_dup(load_live_in_paths_list(body));
749  pips_debug_effects(3, "live in paths of loop body:\n", l_live_in_body);
750 
751  if (!before_p)
752  {
753  pips_debug(1, "do while loop: live in paths are those of the body\n");
754  l_live_in_loop = l_live_in_body;
755  }
756  else
757  {
758  /* the live in paths of the loop are either those of the
759  * first iteration if there is one, or the live out paths
760  * of the whole loop is there is no iteration;
761  * we must remove the write effects and add the in effects
762  * of the condition evaluation
763  */
764 
765  /* As we currently only compute simple live paths,
766  * I wonder if there is a difference with the live out paths
767  * of the loop body...
768  */
769 
770  /* Get the live out paths of the whole loop
771  */
773  pips_debug_effects(3, "live out paths of whole loop:\n", l_live_out_loop);
774  effects_to_may_effects(l_live_out_loop); /* It may be executed... */
775 
776  /* ...or the first iteration of the loop body */
777  effects_to_may_effects(l_live_in_body);
778 
779  // functions that can be pointed by effects_union_op:
780  // ProperEffectsMustUnion
781  // RegionsMustUnion
782  // ReferenceUnion
783  // EffectsMustUnion
784  list l_live_out_after_cond =
785  (*effects_union_op)(l_live_out_loop,
786  l_live_in_body,
788 
789  pips_debug_effects(3, "live out paths after first condition evaluation:\n",
790  l_live_out_after_cond);
791 
792  /* Take into account the effects of the condition */
793  list l_prop_cond =
795 
796  list l_write_cond =
798  pips_debug_effects(3, "write effects of condition:\n", l_write_cond);
799 
800  /* We don't have the in effects of the condition evaluation
801  * we safely approximate them by its may read proper effects
802  * if there are write effects during its evaluation
803  */
804  list l_in_cond =
806  if (!ENDP(l_write_cond)) effects_to_may_effects(l_in_cond);
807  pips_debug_effects(3, "approximation of in effects of condition:\n",
808  l_in_cond);
809 
810  // functions that can be pointed by effects_union_op:
811  // ProperEffectsMustUnion
812  // RegionsMustUnion
813  // ReferenceUnion
814  // EffectsMustUnion
815  // functions that can be pointed by effects_sup_difference_op:
816  // effects_undefined_binary_operator
817  // RegionsSupDifference
818  // EffectsSupDifference
819  l_live_in_loop =
820  (*effects_union_op)(l_in_cond,
821  (*effects_sup_difference_op)(l_live_out_after_cond,
822  l_write_cond,
825 
826  reset_converted_rw_effects(&l_prop_cond, ctxt);
827  }
828 
829  pips_debug_effects(3, "live in paths of loop:\n", l_live_in_loop);
830 
831  store_live_in_paths_list(current_stmt, l_live_in_loop);
832  }
833  else
834  {
835  pips_debug(1, "already bound\n");
836  }
837 
838  pips_debug(1,"end\n");
839 
840  return;
841 }
842 
843 
844 static bool
846 {
847  statement
849  statement
850  body = loop_body(l);
851  entity
852  index = loop_index(l);
853 
854  pips_debug(1,"begin\n");
855 
856  /* First, we get the live out paths of the statement corresponding to the
857  * whole loop
858  */
860  pips_debug_effects(3, "live out paths of whole loop:\n", l_live_out_loop);
861 
862  list l_rw_body = convert_rw_effects(load_rw_effects_list(body),
863  ctxt);
864  list l_w_body = effects_write_effects_dup(l_rw_body);
865  reset_converted_rw_effects(&l_rw_body, ctxt);
866 
867  if (loop_executed_never_p(l)) {
868  //l_w_body must had been a duplicated effect, so need to free them
869  gen_full_free_list(l_w_body);
870  l_w_body = NIL;
871  }
872  else if (!loop_executed_at_least_once_p(l))
873  effects_to_may_effects(l_w_body);
874  // functions that can be pointed by effects_sup_difference_op:
875  // effects_undefined_binary_operator
876  // RegionsSupDifference
877  // EffectsSupDifference
878  l_live_out_loop = (*effects_sup_difference_op)(l_live_out_loop, l_w_body,
880  pips_debug_effects(3, "live out paths of an iteration due to live out paths of whole loop\n", l_live_out_loop);
881 
882 
883  /* We then compute the live out paths of the loop body */
884  /* The live out paths of an iteration are the paths that
885  * - belong to the in effects of the next iterations if there exist some,
886  * except for the loop locals if the loop is parallel;
887  * - or belong to the live out of the whole loop if the next iteration
888  * does not exist.
889  * - to these, for the C language, we must add the read effects resulting
890  * from the evaluation of the incremental expression and of the upper
891  * bound. This includes an exact path for the loop index.
892  */
893  list l_masked_vars = NIL;
894  if(loop_parallel_p(l))
895  l_masked_vars = loop_locals(l);
896 
897  list l_inv_in_body = convert_in_effects(load_invariant_in_effects_list(body), ctxt);
898  list l_inv_in_body_may =
899  effects_dup_without_variables(l_inv_in_body, l_masked_vars);
900  effects_to_may_effects(l_inv_in_body_may);
901  pips_debug_effects(3, "(may) live in paths of an iteration:\n", l_inv_in_body_may);
902 
903  // functions that can be pointed by effects_union_op:
904  // ProperEffectsMustUnion
905  // RegionsMustUnion
906  // ReferenceUnion
907  // EffectsMustUnion
908  list l_live_out_body = (*effects_union_op)(l_live_out_loop,
909  l_inv_in_body_may,
911  reset_converted_in_effects(&l_inv_in_body, ctxt);
912 
914  ctxt);
915  list l_live_in_header =
917  reset_converted_rw_effects(&l_prop_header, ctxt);
918  // functions that can be pointed by reference_to_effect_func:
919  // reference_to_simple_effect
920  // reference_to_convex_region
921  // reference_to_reference_effect
922  list l_index = CONS(EFFECT,
924  NIL);
925  // functions that can be pointed by effects_union_op:
926  // ProperEffectsMustUnion
927  // RegionsMustUnion
928  // ReferenceUnion
929  // EffectsMustUnion
930  l_live_in_header = (*effects_union_op)(l_index, l_live_in_header, effects_same_action_p);
931 
932  pips_debug_effects(3, "live in paths of loop header:\n", l_live_in_header);
933 
934  // functions that can be pointed by effects_union_op:
935  // ProperEffectsMustUnion
936  // RegionsMustUnion
937  // ReferenceUnion
938  // EffectsMustUnion
939  l_live_out_body = (*effects_union_op)(l_live_out_body,
940  l_live_in_header,
942 
943  pips_debug_effects(3, "live out paths of loop body:\n", l_live_out_body);
944 
945  store_live_out_paths_list(body, l_live_out_body);
946 
947  pips_debug(1,"end\n");
948  return true;
949 }
950 
951 static void
953 {
954  /* The live in paths of a loop statement are the live in paths of its header
955  * plus the live in paths of its first iteration if it is exectuted
956  */
957 
958  statement
960  statement
961  body = loop_body(l);
962  entity
963  index = loop_index(l);
964 
965  pips_debug(1,"begin\n");
966 
967  /* If the loop belongs to a sequence of statements, which is
968  * generally the case, its live in paths have already been computed.
969  * I don't yet know if they may be much more precisely computed here.
970  * For performance reasons, I don't try to recompute them if they
971  * are already available.
972  * The code below is likely to be seldom executed;
973  * however, it has been tested on small cases.
974  */
976  {
977 
978  /* Live in effects of header */
979  /* We assume that there is no side effect in the loop header;
980  * thus the live in effects of the header are similar to its proper read effects
981  */
983  ctxt);
984  list l_live_in_header =
986  reset_converted_rw_effects(&l_prop_header, ctxt);
987  pips_debug_effects(3, "live in paths of loop header:\n", l_live_in_header);
988 
989  /* Live in effects of first iteration if it exists minus read effects
990  * on the loop index, which are masked by its initialization in the header,
991  * and read effects on loop locals if the loop is parallel;
992  */
993  list l_masked_vars = NIL;
994  if(loop_parallel_p(l))
995  l_masked_vars = loop_locals(l);
996  /* beware: potential sharing with loop_locals(l) */
997  l_masked_vars = CONS(ENTITY, index, l_masked_vars);
998 
999  list l_live_in_first_iter =
1001  l_masked_vars);
1002 
1003  /* free l_masked_vars: beware of the potential sharing with loop_locals */
1004  if (loop_parallel_p(l) && !ENDP(l_masked_vars))
1005  CDR(l_masked_vars) = NIL;
1006  gen_free_list(l_masked_vars);
1007 
1008  if (! normalizable_and_linear_loop_p(index, loop_range(l)))
1009  {
1010  pips_debug(7, "non linear loop range.\n");
1011  effects_to_may_effects(l_live_in_first_iter);
1012  }
1013  // functions that can be pointed by loop_descriptor_make_func:
1014  // loop_undefined_descriptor_make
1015  // loop_convex_descriptor_make
1017  {
1018  if (loop_executed_never_p(l)) {
1019  //l_live_in_first_iter must had been a duplicated effect, so need to free them
1020  gen_full_free_list(l_live_in_first_iter);
1021  l_live_in_first_iter = NIL;
1022  }
1023  else if (!loop_executed_at_least_once_p(l))
1024  effects_to_may_effects(l_live_in_first_iter);
1025  }
1026  else
1027  {
1028  pips_internal_error("live paths of loop not implemented for convex paths\n");
1029  }
1030 
1031  pips_debug_effects(3, "live in paths of loop first iteration:\n", l_live_in_header);
1032 
1033  /* put them together */
1034  // functions that can be pointed by effects_union_op:
1035  // ProperEffectsMustUnion
1036  // RegionsMustUnion
1037  // ReferenceUnion
1038  // EffectsMustUnion
1039  list l_live_in_loop = (*effects_union_op)(l_live_in_header,
1040  l_live_in_first_iter,
1042 
1043  pips_debug_effects(3, "live in paths of loop:\n", l_live_in_loop);
1044 
1045  store_live_in_paths_list(current_stmt, l_live_in_loop);
1046  }
1047 
1048  pips_debug(1,"end\n");
1049 }
1050 
1051 static bool
1054 {
1055  statement
1057 
1058  pips_debug(1,"begin\n");
1059 
1060  /* First, we get the live out paths of the statement corresponding to the test
1061  */
1062  list l_live_out_test = load_live_out_paths_list(current_stmt);
1063 
1064  /* The live out paths for each branch are the live_out_paths
1065  of the test
1066  */
1067  store_live_out_paths_list(test_true(t), effects_dup(l_live_out_test));
1068  store_live_out_paths_list(test_false(t), effects_dup(l_live_out_test));
1069 
1070 
1071  /* The live in paths of the test are computed with the surrounding
1072  sequence live paths computation.
1073  */
1074  pips_debug(1,"end\n");
1075 
1076  return true;
1077 }
1078 
1079 static bool
1082 {
1084  list l_stmt = sequence_statements(seq);
1085 
1086  pips_debug(1, "begin\n");
1087 
1088  if (ENDP(l_stmt))
1089  {
1090  if (get_bool_property("WARN_ABOUT_EMPTY_SEQUENCES"))
1091  pips_user_warning("empty sequence\n");
1092  store_live_in_paths_list(seq_stmt, NIL);
1093  }
1094  else
1095  {
1096  list l_rev_stmt = NIL; /* reversed version of the sequence to avoid recursion*/
1097  FOREACH(STATEMENT, stmt, l_stmt)
1098  {
1099  l_rev_stmt = CONS(STATEMENT, stmt, l_rev_stmt);
1100  }
1101 
1102  list l_next_stmt_live_in = load_live_out_paths_list(seq_stmt);
1103  FOREACH(STATEMENT, stmt, l_rev_stmt)
1104  {
1105  /* the live out paths of the current statement are the live in paths
1106  of the next statement (or the live out of the while block
1107  if last statement)
1108  */
1109  pips_debug(1,"dealing with statement with ordering: %03zd and number: %03zd\n",
1111 
1112  list l_live_out = l_next_stmt_live_in;
1113  pips_debug_effects(2, "storing effects:\n", l_live_out);
1115 
1116  /* Now let us compute the live in paths */
1118  l_next_stmt_live_in = load_live_in_paths_list(stmt);
1119  }
1120 
1121  /* The block live in paths are the live in paths of the first statement
1122  which is the last visited statement.
1123  However, in case of nested sequences, which may be the case when there are
1124  macros for instance, the live_in paths may have already been computed.
1125  It's not yet clear if the effects we have just computed are more precise
1126  or not.
1127  */
1128  if ( !bound_live_in_paths_p(seq_stmt) )
1129  {
1130  pips_debug_effects(2, "storing live_in paths of sequence statement:\n", l_next_stmt_live_in);
1131  store_live_in_paths_list(seq_stmt, effects_dup(l_next_stmt_live_in));
1132  }
1133 
1134  gen_free_list(l_rev_stmt);
1135  }
1136  pips_debug(1, "end\n");
1137 
1138  return true;
1139 }
1140 
1141 /*
1142 static bool
1143 live_paths_from_instruction_to_expression(
1144  instruction instr,
1145  _UNUSED_ live_paths_analysis_context *ctxt)
1146 {
1147  if (instruction_expression_p(instr))
1148  {
1149  }
1150  return false;
1151 }
1152 */
1153 
1154 static void
1156 {
1157 
1159  (stmt, ctxt,
1161  //instruction_domain, live_paths_from_instruction_to_expression, gen_null,
1162  /* for expression instructions solely, equivalent to gen_true otherwise */
1169 
1170  /* Stop on these nodes: */
1171  call_domain, gen_false, gen_null, /* calls are treated in another phase*/
1173  NULL);
1174 
1175  return;
1176 }
1177 
1179 {
1180  debug_on("LIVE_PATHS_DEBUG_LEVEL");
1181  pips_debug(1, "begin\n");
1182 
1184 
1185  /* Get the code of the module. */
1187  db_get_memory_resource(DBR_CODE, module_name, true) );
1189 
1190 
1192  // functions that can be pointed by effects_computation_init_func:
1193  // effects_computation_no_init
1194  // init_convex_in_out_regions
1195  // init_convex_rw_regions
1196  (*effects_computation_init_func)(module_name);
1197 
1198  /* Get the various effects and in_effects of the module. */
1199 
1203 
1207 
1208 
1209  /* Initialize the map for live_out and live_int paths */
1212 
1213  /* Get the live_out_summary_paths of the current module */
1214  list l_sum_live_out = (*db_get_live_out_summary_paths_func)(module_name);
1215  /* And stores them as the live out paths of the module statement */
1217 
1218  /* Compute the live paths of the module. */
1220  init_live_paths_context(&ctxt, representation);
1222  reset_live_paths_context(&ctxt);
1223 
1224  pips_debug(1, "end\n");
1225 
1226  (*db_put_live_out_paths_func)(module_name, get_live_out_paths());
1227  (*db_put_live_in_paths_func)(module_name, get_live_in_paths());
1228 
1230  reset_rw_effects();
1232  reset_in_effects();
1237  // functions that can be pointed by effects_computation_reset_func:
1238  // effects_computation_no_reset
1239  // reset_convex_in_out_regions
1240  // reset_convex_rw_regions
1241  (*effects_computation_reset_func)(module_name);
1242 
1244 
1247  pips_debug(1, "end\n");
1248 
1249  debug_off();
1250  return true;
1251 }
1252 
1253 /**************************** GENERIC INTERPROCEDURAL LIVE_OUT REGIONS ANALYSIS */
1254 
1255 /**
1256  * Create a new nsc system from the sc system of a region.
1257  * On this new nsc system only keep live variable.
1258  * /param sc constraint system of the region
1259  * /param ref reference variable that the region carry, have to keep on the new system of constraints
1260  * /param llivein list of live in effect, variables to keep
1261  * /param lliveout list of live out effect, variables to keep
1262  * /return a new system of constraint for the region that only keep live variable
1263  */
1265  Pbase base_keep = NULL;
1266  Pbase base_pj = base_copy(sc_base(sc));
1267  Psysteme nsc = sc_dup(sc);
1268 
1269  // Compute list of variable to keep
1270  entity ent = reference_variable(ref);
1271  if (base_contains_variable_p(base_pj, (Variable) ent))
1272  base_keep = base_add_variable(base_keep, (Variable) ent);
1273  list lind = reference_indices(ref);
1274  FOREACH(EXPRESSION, expind, lind) {
1275  entity entind = expression_to_entity(expind);
1276  if (base_contains_variable_p(base_pj, (Variable) entind))
1277  base_keep = base_add_variable(base_keep, (Variable) entind);
1278  }
1279 
1280  FOREACH(EFFECT, live, llivein) {
1281  reference liveref = effect_any_reference(live);
1282  entity liveent = reference_variable(liveref);
1283  if (base_contains_variable_p(base_pj, (Variable) liveent))
1284  base_keep = base_add_variable(base_keep, (Variable) liveent);
1285  }
1286 
1287  FOREACH(EFFECT, live, lliveout) {
1288  reference liveref = effect_any_reference(live);
1289  entity liveent = reference_variable(liveref);
1290  if (base_contains_variable_p(base_pj, (Variable) liveent))
1291  if (!base_contains_variable_p(base_keep, (Variable) liveent))
1292  base_keep = base_add_variable(base_keep, (Variable) liveent);
1293  }
1294 
1295  // Compute list of variable to project
1296  BASE_FOREACH(keep, base_keep) {
1297  vect_erase_var(&base_pj, keep);
1298  }
1299 
1300  ifdebug (4) {
1301  pips_debug(4, "Input system:\n");
1303  pips_debug(4, "Variables to project:\n");
1305  }
1306 
1307  // Project variable if possible
1308  // if not (overflow), keep the variable and generate a warning
1309  // if we use sc_projection_ofl_along_variables what we keep in case of overflow?
1310  //sc_projection_ofl_along_variables(nsc, elim); //add CATCH/TRY
1311  Psysteme scbackup = NULL;
1312  BASE_FOREACH(elim, base_pj) {
1313  scbackup = sc_dup(nsc);
1315  pips_user_warning("An overflow appear for the projection of %s. So this variable wasn't remove from the constraints system.\n", entity_name((entity) elim));
1316  nsc = sc_free(nsc);
1317  nsc = sc_dup(scbackup);
1318  }
1319  TRY {
1320  sc_projection_along_variable_ofl_ctrl(&nsc, elim, FWD_OFL_CTRL);
1321  sc_base_remove_variable(nsc, elim);
1322  nsc = sc_normalize(nsc);
1324  }
1325  scbackup = sc_free(scbackup);
1326  }
1327 
1328  ifdebug (4) {
1329  pips_debug(4, "New system:\n");
1331  }
1332 
1333  return nsc;
1334 }
1335 
1336 /**
1337  * For each statement store the new live_out_regions
1338  */
1340  ifdebug(1) {
1341  pips_debug(1, "begin with statement:\n");
1342  print_statement(st);
1343  }
1344  list llivein = load_live_in_paths_list(st);
1345  list lliveout = load_live_out_paths_list(st);
1346  list loutregions = load_statement_out_regions(st);
1347  list lliveoutreg = NIL;
1348 
1349  FOREACH(EFFECT, reg, loutregions) {
1350  reference rreg = effect_any_reference(reg);
1351  descriptor dreg = effect_descriptor(reg);
1352  switch (descriptor_tag(dreg)) {
1353  case is_descriptor_none:
1354  pips_debug(3, "scalar region");
1355  lliveoutreg = CONS(EFFECT, (*effect_dup_func)(reg), lliveoutreg);
1356  break;
1357  case is_descriptor_convex:
1358  {
1359  pips_debug(3, "convex region");
1360  Psysteme sc = descriptor_convex(dreg);
1361  Psysteme nsc = new_system_with_only_live_variable(sc, rreg, llivein, lliveout);
1362  effect r = make_effect(
1363  copy_cell(effect_cell(reg)),
1364  copy_action(effect_action(reg)),
1366  make_descriptor_convex(nsc) );
1367  lliveoutreg = CONS(EFFECT, r, lliveoutreg);
1368  break;
1369  }
1371  pips_debug(3, "convex union region");
1372  pips_internal_error("Not done yet...\n");
1373  //can use new_system_with_only_live_variable for each sc
1374  break;
1375  default:
1376  pips_internal_error("This case never occurs\n descriptor = %d\n", descriptor_tag(dreg));
1377  break;
1378  }
1379  }
1380 
1381  // memorize the new live_out_regions for the statement.
1382  store_live_out_regions_list(st, lliveoutreg);
1383 
1384  ifdebug(1) {
1385  pips_debug(1, "end statement:\n");
1386  print_statement(st);
1387  }
1388  return true;
1389 }
1390 
1391 /**
1392  *
1393  */
1396  bool good_result_p = true;
1397 
1398  debug_on("GMRE_DEBUG_LEVEL");
1399  pips_debug(1, "begin\n");
1400 
1401  //-- configure environment --//
1403 
1405  db_get_memory_resource(DBR_CODE, module_name, true) );
1407 
1408  pips_assert("Statement should be OK before...",
1410 
1412 
1413  //-- get dependencies --//
1415  db_get_memory_resource(DBR_OUT_REGIONS, module_name, true));
1417  db_get_memory_resource(DBR_LIVE_OUT_PATHS, module_name, true));
1419  db_get_memory_resource(DBR_LIVE_IN_PATHS, module_name, true));
1420 
1421 
1422  //-- Make the job -- //
1425 
1426  //-- Save modified code to database --//
1427  DB_PUT_MEMORY_RESOURCE(DBR_LIVE_OUT_REGIONS, module_name,
1429 
1430 
1431  //-- reset module and dependencies --//
1434 
1439 
1440  pips_debug(1, "end\n");
1441  debug_off();
1442 
1443  return (good_result_p);
1444 }
1445 
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
action copy_action(action p)
ACTION.
Definition: effects.c:77
descriptor make_descriptor_convex(Psysteme _field_)
Definition: effects.c:439
approximation copy_approximation(approximation p)
APPROXIMATION.
Definition: effects.c:132
effect make_effect(cell a1, action a2, approximation a3, descriptor a4)
Definition: effects.c:484
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
bool statement_consistent_p(statement p)
Definition: ri.c:2195
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static statement module_statement
Definition: alias_check.c:125
static const char * caller_name
Definition: alias_check.c:122
static entity callee
Definition: alias_pairs.c:62
#define CATCH(what)
@ overflow_error
#define UNCATCH(what)
#define TRY
Pbase base_add_variable(Pbase b, Variable var)
Pbase base_add_variable(Pbase b, Variable v): add variable v as a new dimension to basis b at the end...
Definition: base.c:88
bool base_contains_variable_p(Pbase b, Variable v)
bool base_contains_variable_p(Pbase b, Variable v): returns true if variable v is one of b's elements...
Definition: base.c:136
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
static statement current_stmt
#define pips_debug_effects(level, message, l_eff)
effects_representation_val
void free_effects_private_current_context_stack(void)
void set_invariant_in_effects(statement_effects)
void set_cumulated_in_effects(statement_effects)
void init_live_out_regions(void)
void reset_live_out_regions(void)
void set_live_in_paths(statement_effects)
list effects_store_effects(list)
statement_effects(* db_get_invariant_in_effects_func)(const char *)
void set_rw_effects(statement_effects)
void reset_invariant_in_effects(void)
void effects_to_may_effects(list)
list effects_read_effects_dup(list)
void reset_live_out_paths(void)
void make_effects_private_current_context_stack(void)
list load_live_out_paths_list(statement)
statement_effects(* db_get_live_in_paths_func)(const char *)
list generic_effects_forward_translation(entity, list, list, transformer)
void init_live_out_paths(void)
list load_live_in_paths_list(statement)
statement_effects get_live_out_regions(void)
list proper_to_summary_effects(list)
list load_invariant_in_effects_list(statement)
void reset_cumulated_in_effects(void)
statement_effects(* db_get_invariant_rw_effects_func)(const char *)
statement_effects(* db_get_live_out_paths_func)(const char *)
void init_live_in_paths(void)
list effects_write_effects_dup(list)
list load_proper_rw_effects_list(statement)
descriptor(* loop_descriptor_make_func)(loop)
effect(* reference_to_effect_func)(reference, action, bool)
void reset_out_effects(void)
void set_live_out_paths(statement_effects)
descriptor loop_undefined_descriptor_make(loop)
void store_live_out_regions_list(statement, list)
void reset_proper_rw_effects(void)
statement_effects get_live_in_paths(void)
void set_proper_rw_effects(statement_effects)
bool normalizable_and_linear_loop_p(entity, range)
list load_in_effects_list(statement)
statement_effects(* db_get_cumulated_in_effects_func)(const char *)
void set_out_effects(statement_effects)
statement_effects get_live_out_paths(void)
void set_in_effects(statement_effects)
void reset_in_effects(void)
list effects_dup(list)
list filter_effects_with_declaration(list, entity)
list load_rw_effects_list(statement)
void store_live_in_paths_list(statement, list)
void store_live_out_paths_list(statement, list)
void reset_invariant_rw_effects(void)
list load_statement_out_regions(statement)
bool bound_live_in_paths_p(statement)
effect(* effect_dup_func)(effect eff)
statement_effects(* db_get_in_effects_func)(const char *)
void reset_live_in_paths(void)
bool r_w_combinable_p(effect, effect)
bool bound_live_out_paths_p(statement)
list effects_dup_without_variables(list, list)
void set_invariant_rw_effects(statement_effects)
statement_effects(* db_get_proper_rw_effects_func)(const char *)
void reset_rw_effects(void)
bool effects_same_action_p(effect, effect)
statement_effects(* db_get_rw_effects_func)(const char *)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
action make_action_read_memory(void)
Definition: effects.c:1017
#define descriptor_tag(x)
Definition: effects.h:595
#define effect_action(x)
Definition: effects.h:642
@ is_descriptor_none
Definition: effects.h:576
@ is_descriptor_convexunion
Definition: effects.h:574
@ is_descriptor_convex
Definition: effects.h:575
#define effect_descriptor(x)
Definition: effects.h:646
#define descriptor_convex(x)
Definition: effects.h:601
#define effect_approximation(x)
Definition: effects.h:644
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#define effect_cell(x)
Definition: effects.h:640
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
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void gen_full_free_list(list l)
Definition: genClib.c:1023
#define UNSTRUCTURED_CONTROL_MAP(c, u, l, code)
Walk through all the controls of un unstructured.
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
gen_chunk * gen_get_ancestor(int, const void *)
return the first ancestor object found of the given type.
Definition: genClib.c:3560
bool gen_false(__attribute__((unused)) gen_chunk *unused)
Return false and ignore the argument.
Definition: genClib.c:2796
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
bool loop_parallel_p(loop l)
Test if a loop is parallel.
Definition: loop.c:393
bool loop_executed_never_p(loop l)
Check if loop bound are constant and then if upper < lower.
Definition: loop.c:971
bool loop_executed_at_least_once_p(loop l)
Check if loop bound are constant and then if upper >= lower.
Definition: loop.c:937
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define list_undefined_p(c)
Return if a list is undefined.
Definition: newgen_list.h:75
#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
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 list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
void vect_fprint(FILE *f, Pvecteur v, get_variable_name_t variable_name)
void vect_fprint(FILE * f, Pvecteur v, char * (*variable_name)()): impression d'un vecteur creux v su...
Definition: io.c:124
static void init_live_paths_context(live_paths_analysis_context *ctxt, effects_representation_val representation)
static bool live_paths_from_block_to_statements(sequence seq, live_paths_analysis_context *ctxt)
static void reset_converted_rw_effects(list *lrw, live_paths_analysis_context *ctxt)
static void reset_converted_in_effects(list *lin, live_paths_analysis_context *ctxt)
static list convert_rw_effects(list lrw, live_paths_analysis_context *ctxt)
static void update_live_out_summary_engine_context_paths(live_out_summary_engine_context *ctxt, list l_paths)
static bool live_out_paths_from_call_site_to_callee(call c, live_out_summary_engine_context *ctxt)
static bool live_out_paths_from_forloop_to_body(forloop l, live_paths_analysis_context *ctxt)
bool live_paths_engine(const char *module_name, effects_representation_val representation)
static void live_paths_of_module_statement(statement stmt, live_paths_analysis_context *ctxt)
static Psysteme new_system_with_only_live_variable(Psysteme sc, reference ref, list llivein, list lliveout)
Create a new nsc system from the sc system of a region.
static void reset_live_out_summary_engine_context(live_out_summary_engine_context *ctxt)
static void live_in_paths_of_loop(loop l, live_paths_analysis_context *ctxt)
static bool live_out_paths_from_test_to_branches(test t, _UNUSED_ live_paths_analysis_context *ctxt)
static void live_out_paths_from_caller_to_callee(entity caller, entity callee, live_out_summary_engine_context *ctxt)
static bool live_out_paths_from_loop_to_body(loop l, live_paths_analysis_context *ctxt)
static bool live_out_paths_from_whileloop_to_body(whileloop l, live_paths_analysis_context *ctxt)
static void live_in_paths_of_statement(statement s, live_paths_analysis_context *ctxt)
static void live_in_paths_of_whileloop(whileloop l, live_paths_analysis_context *ctxt)
bool live_out_summary_paths_engine(const char *module_name)
static bool filter_live_out_regions_statement(statement st)
For each statement store the new live_out_regions.
static bool live_out_summary_paths_stmt_filter(statement s, __attribute__((unused)) live_out_summary_engine_context *ctxt)
static list convert_in_effects(list lin, live_paths_analysis_context *ctxt)
static void set_live_out_summary_engine_context(live_out_summary_engine_context *ctxt, entity callee)
bool live_in_summary_paths_engine(const char *module_name)
liveness_analysis_engine.c
static bool live_out_paths_from_unstructured_to_nodes(unstructured unstr, live_paths_analysis_context *ctxt)
static void reset_live_paths_context(live_paths_analysis_context *ctxt)
bool live_out_region_engine(const char *module_name, __attribute__((unused)) effects_representation_val representation)
#define debug_on(env)
Definition: misc-local.h:157
#define _UNUSED_
Definition: misc-local.h:232
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
void set_bool_property(const char *, bool)
bool static_area_p(entity aire)
Definition: area.c:77
bool c_module_p(entity m)
Test if a module "m" is written in C.
Definition: entity.c:2777
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
void free_statement_global_stack(void)
Definition: static.c:358
void make_statement_global_stack(void)
Definition: static.c:318
#define forloop_domain
newgen_extensions_domain_defined
Definition: ri.h:178
#define loop_body(x)
Definition: ri.h:1644
#define test_domain
newgen_entity_domain_defined
Definition: ri.h:418
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#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 loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define control_predecessors(x)
Definition: ri.h:943
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define statement_ordering(x)
Definition: ri.h:2454
#define test_false(x)
Definition: ri.h:2837
#define whileloop_evaluation(x)
Definition: ri.h:3166
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
#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 EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined
Definition: ri.h:2761
#define entity_name(x)
Definition: ri.h:2790
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define reference_indices(x)
Definition: ri.h:2328
#define control_successors(x)
Definition: ri.h:945
#define unstructured_exit(x)
Definition: ri.h:3006
#define loop_locals(x)
Definition: ri.h:1650
#define whileloop_body(x)
Definition: ri.h:3162
#define whileloop_domain
newgen_variable_domain_defined
Definition: ri.h:466
#define statement_declarations(x)
Definition: ri.h:2460
#define storage_ram(x)
Definition: ri.h:2521
#define loop_range(x)
Definition: ri.h:1642
#define call_arguments(x)
Definition: ri.h:711
#define control_statement(x)
Definition: ri.h:941
#define statement_number(x)
Definition: ri.h:2452
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
#define evaluation_before_p(x)
Definition: ri.h:1159
#define forloop_body(x)
Definition: ri.h:1372
#define loop_index(x)
Definition: ri.h:1640
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
void sc_base_remove_variable(Psysteme sc, Variable v)
Definition: sc.c:239
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
char * default_variable_to_string(Variable v)
Definition: sc_debug.c:245
void sc_print(Psysteme ps, get_variable_name_t nom_var)
void sc_print()
Definition: sc_io.c:194
Psysteme sc_free(Psysteme in_ps)
Psysteme sc_free( in_ps ) AL 30/05/94 Free of in_ps.
Definition: sc_list.c:112
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
Psysteme sc_normalize(Psysteme ps)
Psysteme sc_normalize(Psysteme ps): normalisation d'un systeme d'equation et d'inequations lineaires ...
#define ifdebug(n)
Definition: sg.c:47
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
effects_representation_val representation
Definition: statement.c:54
@ keep
bj > b1 -> h1/hj = h1
Definition: union-local.h:61
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62
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 FWD_OFL_CTRL
#define BASE_FOREACH(v, b)
Pbase base_copy(Pbase b)
Direct duplication.
Definition: alloc.c:300
void vect_erase_var(Pvecteur *ppv, Variable v)
void vect_erase_var(Pvecteur * ppv, Variable v): projection du vecteur *ppv selon la direction v (i....
Definition: unaires.c:106