PIPS
in_effects_engine.c
Go to the documentation of this file.
1 /*
2 
3  $Id: in_effects_engine.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* package generic effects : Be'atrice Creusillet 5/97
28  *
29  * File: in_effects_engine.c
30  * ~~~~~~~~~~~~~~~~~~~~~~~~~
31  *
32  * This File contains the generic functions necessary for the computation of
33  * all types of in effects.
34  *
35  */
36 #include <stdio.h>
37 #include <string.h>
38 
39 #include "genC.h"
40 
41 #include "linear.h"
42 
43 #include "misc.h"
44 
45 #include "text.h"
46 #include "ri.h"
47 #include "effects.h"
48 
49 #include "text-util.h"
50 #include "ri-util.h"
51 #include "prettyprint.h" // for debugging
52 #include "effects-util.h"
53 
54 #include "properties.h"
55 
56 // for add_intermediate_value() and entity_to_intermediate_value()
57 #include "transformer.h"
58 
59 #include "pipsdbm.h"
60 #include "workspace-util.h"
61 
62 #include "effects-generic.h"
63 
64 typedef struct {
65  bool memory_effects_only;
66  bool memory_in_out_effects_only;
67  effects_representation_val representation;
68 } in_effects_context;
69 
70 
71 static void init_in_effects_context(in_effects_context *ctxt,
72  effects_representation_val representation)
73 {
74  ctxt->memory_effects_only = get_bool_property("MEMORY_EFFECTS_ONLY");
75  ctxt->memory_in_out_effects_only = get_bool_property("MEMORY_IN_OUT_EFFECTS_ONLY");
76 
77  if (! ctxt->memory_effects_only
78  && ctxt->memory_in_out_effects_only)
79  // if the MEMORY_EFFECTS_ONLY is FALSE on input, and
80  // we don't want to compute IN non-memory effects,
81  // we have to temporarily set MEMORY_EFFECTS_ONLY to
82  // TRUE so that functions computing R/W effects
83  // do not compute non memory effects which would have to be filtered.
84  set_bool_property("MEMORY_EFFECTS_ONLY", true);
85  ctxt->representation = representation;
86 }
87 
88 static void reset_in_effects_context(in_effects_context *ctxt)
89 {
90  if (! ctxt->memory_effects_only
91  && ctxt->memory_in_out_effects_only)
92  // if the MEMORY_EFFECTS_ONLY is FALSE on input, and
93  // we did not want to compute IN non-memory effects,
94  // we have to reset MEMORY_EFFECTS_ONLY to FALSE.
95  set_bool_property("MEMORY_EFFECTS_ONLY", false);
96 }
97 
98 static list convert_rw_effects(list lrw, in_effects_context *ctxt)
99 {
100  if (!ctxt->memory_effects_only
101  && ctxt->memory_in_out_effects_only)
102  lrw = effects_store_effects(lrw);
103 
104  return lrw;
105 }
106 
107 
108 static void reset_converted_rw_effects(list *lrw, in_effects_context *ctxt)
109 {
110  if (!ctxt->memory_effects_only
111  && ctxt->memory_in_out_effects_only)
112  gen_free_list(*lrw);
113  *lrw = NIL;
114 }
115 
116 /* =============================================================================
117  *
118  * GENERIC INTERPROCEDURAL IN EFFECTS ANALYSIS
119  *
120  * =============================================================================
121  */
122 
123 
124 /* bool summary_in_effects_engine(const char* module_name)
125  * input : the name of the current module.
126  * output : the list of summary in effects
127  * modifies : nothing.
128  * comment : computes the summary in effects of the current module, using the
129  * in effects of its embedding statement.
130  */
131 bool
133 {
134  list l_glob = NIL, l_loc = NIL;
135  statement module_stat;
136 
139  db_get_memory_resource(DBR_CODE, module_name, true) );
140  module_stat = get_current_module_statement();
141  make_statement_global_stack(); // for calls to semantics libray
142 
143  // functions that can be pointed by effects_computation_init_func:
144  // effects_computation_no_init
145  // init_convex_in_out_regions
146  // init_convex_rw_regions
147  (*effects_computation_init_func)(module_name);
148 
150 
151  l_loc = load_in_effects_list(module_stat);
152 
153  // functions that can be pointed by effects_local_to_global_translation_op:
154  // effects_dynamic_elim
155  // regions_dynamic_elim
156  l_glob = (*effects_local_to_global_translation_op)(l_loc);
157 
158  (*db_put_summary_in_effects_func)(module_name, l_glob);
159 
160 
163  free_statement_global_stack(); // for calls to semantics libray
165 
166  // functions that can be pointed by effects_computation_reset_func:
167  // effects_computation_no_reset
168  // reset_convex_in_out_regions
169  // reset_convex_rw_regions
170  (*effects_computation_reset_func)(module_name);
171 
172  return true;
173 }
174 
175 
176 /***************************** GENERIC INTRAPROCEDURAL IN EFFECTS ANALYSIS */
177 
178 /*
179 typedef void (*void_fun)();
180 static void list_gen_consistent_p(list l)
181 {
182  pips_debug(1, "length is %d\n", gen_length(l));
183  gen_map((void_fun)gen_consistent_p, l);
184  gen_consistent_p(get_in_effects());
185 }
186 */
187 #define debug_consistent(l) /* ifdebug(9) list_gen_consistent_p(l) */
188 
189 static bool in_effects_stmt_filter(
190  statement s, _UNUSED_ in_effects_context *ctxt)
191 {
192  pips_debug(1, "Entering statement %03zd :\n", statement_ordering(s));
195  return true;
196 }
197 
198 static void in_effects_of_statement(
199  statement s, _UNUSED_ in_effects_context *ctxt)
200 {
202  debug_consistent(NIL);
205  pips_debug(1, "End statement %03zd :\n", statement_ordering(s));
206 }
207 
208 /**
209  computes the in effects of the declarations from the list of
210  effects after the declaration
211 
212  @param[out] lin_after_decls is the list of effects in the store after the declarations;
213  it is modified.
214  @param[in] l_decl is the ordered list of declarations.
215 
216  usage: l = rw_effects_of_declarations(l, l_decl)
217  */
218 static list in_effects_of_declarations(
219  list lin_after_decls, list l_decl,
220  in_effects_context *ctxt)
221 {
222  list lin_before_decls = NIL; /* the returned list */
223  list lin_after_first_decl = NIL; /* effects after first declaration */
224 
225  if (!ENDP(l_decl))
226  {
227  // treat last declarations first to compute the in effects in the store juste after
228  // the first declaration
229  if (!ENDP(CDR(l_decl)))
230  lin_after_first_decl = in_effects_of_declarations(lin_after_decls, CDR(l_decl), ctxt);
231  else
232  lin_after_first_decl = lin_after_decls;
233 
234  // then handle top declaration
235  entity decl = ENTITY(CAR(l_decl));
236  storage decl_s = entity_storage(decl);
237 
238  ifdebug(8)
239  {
240  type ct = entity_basic_concrete_type(decl);
241  pips_debug(8, "dealing with entity : %s with type %s\n",
243  }
244 
245  if (storage_ram_p(decl_s)
246  /* static variable declaration has no effect, even in case of initialization. */
248  && type_variable_p(entity_type(decl)))
249  {
250  value v_init = entity_initial(decl);
251  expression exp_init = expression_undefined;
252  if(value_expression_p(v_init))
253  exp_init = value_expression(v_init);
254 
255  // filter l_rw_after_decls with the declaration
256  lin_after_first_decl = filter_effects_with_declaration(lin_after_first_decl, decl);
257 
258  // and then add the in effects and remove the write effects
259  // due to the initialization part
260  // we should also apply the transformer of this expression
261  // but this not currently implemented.
262  if(!expression_undefined_p(exp_init))
263  {
264  /* Here we should compute the IN effects of the expression -
265  * However, there is currently no interface to compute them -
266  * So I take the read effects of the expression.
267  * If the expression has write effects, I change the approximations
268  * to may
269  */
270  list l_full_rw_exp_init = generic_proper_effects_of_expression(exp_init);
271  l_full_rw_exp_init = proper_to_summary_effects(l_full_rw_exp_init);
272  list l_rw_exp_init = convert_rw_effects(l_full_rw_exp_init, ctxt);
273 
274  list l_w_exp_init = effects_write_effects(l_rw_exp_init);
275  list l_r_exp_init = effects_read_effects(l_rw_exp_init);
276 
277  if (!ENDP(l_w_exp_init))
278  effects_to_may_effects(l_r_exp_init);
279 
280  // IN(before decls) = IN(first decl) U (IN(after first decl) - W(first decl))
281  // functions that can be pointed by effects_union_op:
282  // ProperEffectsMustUnion
283  // RegionsMustUnion
284  // ReferenceUnion
285  // EffectsMustUnion
286  // functions that can be pointed by effects_sup_difference_op:
287  // effects_undefined_binary_operator
288  // RegionsSupDifference
289  // EffectsSupDifference
290  lin_before_decls = (*effects_union_op)(
291  effects_dup(l_r_exp_init),
292  (*effects_sup_difference_op)(lin_after_first_decl,
293  effects_dup(l_w_exp_init), r_w_combinable_p),
295 
296  gen_full_free_list(l_full_rw_exp_init); /* free ell the expression effects */
297  reset_converted_rw_effects(&l_rw_exp_init, ctxt);
298  gen_free_list(l_r_exp_init);
299  gen_free_list(l_w_exp_init);
300  }
301  else
302  lin_before_decls = lin_after_first_decl;
303 
304  } /* if (storage_ram(decl_s) && !static_area_p(ram_section(storage_ram(decl_s)))) */
305  else
306  {
307  lin_before_decls = lin_after_first_decl;
308  }
309  } /* if (!ENDP(CDR(l_decl))) */
310  else
311  lin_before_decls = lin_after_decls;
312  // we should also do some kind of unioning...
313 
314  // this could maybe be placed before, only for generic_proper_effects_of_expression(exp_init) */
315  if (get_constant_paths_p())
316  {
317  list l_tmp = lin_before_decls;
318  lin_before_decls = pointer_effects_to_constant_path_effects(lin_before_decls);
319  effects_free(l_tmp);
320  }
321 
322  return lin_before_decls;
323 }
324 
325 /**
326  *
327  * TODO: There are certainly many memory leak in this piece of code?
328  * NL: but I don't understand enough the code to know
329  * when the lists are modify or when a new list is return...
330  * before my modification (r22288), there certainly are some memory leak
331  * and after it I certainly add more :(...
332  */
333 static list r_in_effects_of_sequence(list l_inst, in_effects_context *ctxt)
334 {
335  statement first_statement;
336  list remaining_block = NIL;
337 
338  list s1_lin; /* in effects of first statement */
339  list rb_lin = NIL; /* in effects of remaining block */
340  list l_in = NIL; /* resulting in effects */
341  list l_cumul_in = NIL; /* cumulated in effects */
342  list s1_lrw; /* rw effects of first statement */
343  transformer t1; /* transformer of first statement */
344 
345  pips_debug(3," begin\n");
346 
347  first_statement = STATEMENT(CAR(l_inst));
348  ifdebug(3)
349  {
350  pips_debug(3," first statement is (ordering %03zd): \n",
351  statement_ordering(first_statement));
352  print_statement(first_statement);
353  }
354  remaining_block = CDR(l_inst);
355 
356  /* Is it the last instruction of the block */
357  if (!ENDP(remaining_block))
358  {
359  // recursively call the function before doing anything else
360  // to avoid large memory usage in case of long sequences
361  rb_lin = r_in_effects_of_sequence(remaining_block, ctxt);
362 
363  ifdebug(6)
364  {
365  pips_debug(6," in effects for remaining block:\n");
366  (*effects_prettyprint_func)(rb_lin);
367  }
368 
369  // move the in effects of the remaining block in the store before the
370  // first statement
371  t1 = (*load_completed_transformer_func)(first_statement);
372 
373  /* Nga Nguyen, 25/04/2002. Bug found in fct.f about the transformer of loops
374  * Preconditions added to regions take into account the loop exit preconditions
375  * but the corresponding loop transformers do not. This may give false results
376  * when applying transformers to regions. So we have to add loop exit conditions
377  * to the transformers. */
378 
379  // if (statement_loop_p(first_statement))
380  // {
381  // loop l = statement_loop(first_statement);
382  // t1 = (*add_loop_exit_condition_func)(t1,l);
383  // }
384 
385  // functions that can be pointed by effects_transformer_composition_op:
386  // effects_composition_with_transformer_nop
387  // effects_undefined_composition_with_transformer
388  // convex_regions_transformer_compose
389  // simple_effects_composition_with_effect_transformer
390  (*effects_transformer_composition_op)(rb_lin, t1);
391 
392  s1_lrw = convert_rw_effects(load_rw_effects_list(first_statement),ctxt);
393  ifdebug(6)
394  {
395  pips_debug(6," rw effects for first statement:\n");
396  (*effects_prettyprint_func)(s1_lrw);
397  }
398  s1_lin = effects_dup(load_in_effects_list(first_statement));
399  ifdebug(6)
400  {
401  pips_debug(6," in effects for first statement:\n");
402  (*effects_prettyprint_func)(s1_lin);
403  }
404 
405  /* Nga Nguyen, 25/04/2002.rb_lin may contain regions with infeasible system {0==-1}
406  * => remove them from rb_lin*/
407  // rb_lin = (*remove_effects_with_infeasible_system_func)(rb_lin);
408 
409  /* IN(block) = (IN(rest_of_block) - W(S1)) U IN(S1) */
410  // functions that can be pointed by effects_union_op:
411  // ProperEffectsMustUnion
412  // RegionsMustUnion
413  // ReferenceUnion
414  // EffectsMustUnion
415  // functions that can be pointed by effects_sup_difference_op:
416  // effects_undefined_binary_operator
417  // RegionsSupDifference
418  // EffectsSupDifference
419  l_cumul_in = (*effects_union_op)(
420  s1_lin,
421  (*effects_sup_difference_op)(effects_dup(rb_lin),
422  effects_dup(s1_lrw),
425 
426  // no leak
427  reset_converted_rw_effects(&s1_lrw,ctxt);
428  } // if (!ENDP(remaining_block))
429  else
430  {
431  l_cumul_in = effects_dup(load_in_effects_list(first_statement));
432  }
433 
434  ifdebug(6)
435  {
436  pips_debug(6,"for statement:\n");
437  print_statement(first_statement);
438  pips_debug(6,"cumulated_in_effects:\n");
439  (*effects_prettyprint_func)(l_cumul_in);
440  debug_consistent(l_cumul_in);
441  }
442  store_cumulated_in_effects_list(first_statement, l_cumul_in);
443 
444  // NL: For declaration statement, we don't want to keep effects
445  // on variables that doesn't exist, for previous statement
446  // (before the declaration).
448  (declaration_statement_p(first_statement) ))
449  {
450  // if it's a declaration statement, effects will be added on the fly
451  // as declarations are handled.
452  pips_debug(5, "first statement is a declaration statement\n");
453  list l_decl = statement_declarations(first_statement);
454  l_in = in_effects_of_declarations(rb_lin, l_decl, ctxt);
455  }
456  else {
457  l_in = effects_dup(l_cumul_in);
458  }
459 
460  //debug_consistent(l_in);
461  return l_in;
462 }
463 
464 static void
465 in_effects_of_sequence(sequence block, in_effects_context *ctxt)
466 {
467  list l_in = NIL;
470 
471  pips_debug(2, "Effects for statement %03zd:\n",
472  statement_ordering(current_stat));
473 
474  if (ENDP(l_inst))
475  {
476  if (get_bool_property("WARN_ABOUT_EMPTY_SEQUENCES"))
477  pips_user_warning("empty sequence\n");
478  }
479  else
480  {
481  l_in = r_in_effects_of_sequence(l_inst, ctxt);
482  }
483 
484  ifdebug(2)
485  {
486  pips_debug(2, "IN effects for statement%03zd:\n",
487  statement_ordering(current_stat));
488  (*effects_prettyprint_func)(l_in);
489  pips_debug(2, "end\n");
490  }
491 
492  store_in_effects_list(current_stat, l_in);
493  debug_consistent(l_in);
494 }
495 
496 
497 
498 static void
499 in_effects_of_test(test t, in_effects_context *ctxt)
500 {
502  list lt, lf, lc_in;
503  list l_in = NIL;
504 
505  pips_debug(2, "Effects for statement %03zd:\n",
506  statement_ordering(current_stat));
507 
508  /* IN effects of the true branch */
509  lt = effects_dup(load_in_effects_list(test_true(t))); /* FC: dup */
510  /* IN effects of the false branch */
511  lf = effects_dup(load_in_effects_list(test_false(t))); /* FC: dup */
512 
513  /* IN effects of the combination of both */
514  // functions that can be pointed by effects_test_union_op:
515  // EffectsMayUnion
516  // RegionsMayUnion
517  // ReferenceTestUnion
518  l_in = (*effects_test_union_op)(lt, lf, effects_same_action_p);
519 
520  /* IN effects of the condition */
521  /* They are equal to the proper read effects of the statement if
522  * there are no side-effects. When there are write effects, we
523  * should compute the in effects of the expression, but we still
524  * use the read effects and turn them to may effects as an
525  * over-approximation.
526  */
527 
528  lc_in = convert_rw_effects(load_proper_rw_effects_list(current_stat),ctxt);
529  list lc_in_r = effects_read_effects_dup(lc_in);
530  if (gen_length(lc_in_r) != gen_length(lc_in))
531  // there are write effects -> conservatively switch to may for the moment
532  effects_to_may_effects(lc_in_r);
533 
534  /* in regions of the test */
535  // functions that can be pointed by effects_union_op:
536  // ProperEffectsMustUnion
537  // RegionsMustUnion
538  // ReferenceUnion
539  // EffectsMustUnion
540  l_in = (*effects_union_op)(l_in, lc_in_r, effects_same_action_p);
541 
542  reset_converted_rw_effects(&lc_in,ctxt);
543 
544  ifdebug(2)
545  {
546  pips_debug(2, "IN effects for statement %03zd:\n",
547  statement_ordering(current_stat));
548  (*effects_prettyprint_func)(l_in);
549  pips_debug(2, "end\n");
550  }
551 
552  store_in_effects_list(current_stat, l_in);
553  debug_consistent(l_in);
554 }
555 
556 /* Rin[for (c) s] = Rr[for (c) s] * may
557  */
558 static void in_effects_of_forloop(forloop f, in_effects_context *ctxt)
559 {
561 
562  pips_debug(1, "considering for loop 0x%p\n", (void *) f);
563 
566  list lin = effects_read_effects_dup(lrw);
567  /* switch to MAY... */
571  reset_converted_rw_effects(&lrw, ctxt);
572 }
573 
574 /* Rin[while (c) s] = Rin[c] U (Rr[while (c) s] * may)
575  */
576 static void in_effects_of_whileloop(whileloop w, in_effects_context *ctxt)
577 {
579  bool before_p = evaluation_before_p(whileloop_evaluation(w));
580 
581  pips_debug(1, "considering while loop 0x%p\n", (void *) w);
582 
585  list l_in = effects_read_effects_dup(l_rw);
586  /* switch to MAY... */
588 
589  /* add the loop condition evaluation effects */
590  if (before_p)
591  {
593  ctxt);
594 
595  pips_debug_effects(3, "effects of condition:\n", l_prop_cond);
596 
597  /* We don't have the in effects of the condition evaluation
598  * we safely approximate them by its may read proper effects
599  * if there are write effects during its evaluation
600  */
601  list l_in_cond = effects_read_effects_dup(l_prop_cond);
602 
603  if ( gen_length(l_in_cond) != gen_length(l_prop_cond))
604  /* there are write effects in the condition */
605  effects_to_may_effects(l_in_cond);
606  else
607  l_in_cond = proper_to_summary_effects(l_in_cond);
608 
609  pips_debug_effects(3, "approximation of in effects of condition:\n", l_in_cond);
610 
611  // functions that can be pointed by effects_union_op:
612  // ProperEffectsMustUnion
613  // RegionsMustUnion
614  // ReferenceUnion
615  // EffectsMustUnion
616  l_in = (*effects_union_op)(l_in,
617  l_in_cond,
619 
620  reset_converted_rw_effects(&l_prop_cond, ctxt);
621  }
622 
625  reset_converted_rw_effects(&l_rw, ctxt);
626 }
627 
628 /* list in_effects_of_loop(loop l)
629  * input : a loop, its transformer and its context.
630  * output : the corresponding list of in regions.
631  * modifies : in_regions_map.
632  * comment : IN(loop) = proj[i] (proj[i'] (IN(i) - W(i', i'<i))) U IN(i=1)
633  */
634 static void in_effects_of_loop(loop l, in_effects_context *ctxt)
635 {
637 
638  list lbody_in; /* in regions of the loop body */
639  list global_in, global_in_read_only;/* in regions of non local variables */
640  list global_write; /* invariant write regions of non local variables */
641  list l_prop, l_prop_read, l_prop_write; /* proper effects of header */
642  list l_in = NIL;
643  transformer loop_trans = transformer_undefined;
644 
645  pips_debug(1, "begin\n");
646 
647  entity i = loop_index(l);
648  range r = loop_range(l);
649  statement b = loop_body(l);
650 
651  pips_debug(1, "loop index %s.\n", entity_minimal_name(i));
652 
653  /* IN EFFECTS OF HEADER */
654  /* We assume that there is no side effect in the loop header;
655  * thus the IN effects of the header are similar to its proper read effects
656  * when there are no side effects.
657  */
658  list l_prop_init = convert_rw_effects(load_proper_rw_effects_list(current_stat), ctxt);
659  l_prop = proper_to_summary_effects(effects_dup(l_prop_init));
660  reset_converted_rw_effects(&l_prop_init, ctxt);
661  l_prop_read = effects_read_effects(l_prop);
662  l_prop_write = effects_write_effects(l_prop);
663  gen_free_list(l_prop);
664  /* END - IN EFFECTS OF HEADER */
665 
666  /* INVARIANT WRITE EFFECTS OF LOOP BODY STATEMENT. */
668  global_write = effects_write_effects_dup(l_inv);
669  reset_converted_rw_effects(&l_inv, ctxt);
670 
671  pips_debug_effects(4, "W(i)= \n", global_write);
672 
673  /* IN EFFECTS OF LOOP BODY STATEMENT. */
674  lbody_in = load_in_effects_list(b);
675 
677  debug_consistent(lbody_in);
678 
679  /* Effects on locals are masked if the loop is parallel */
680  if(loop_parallel_p(l))
681  global_in = effects_dup_without_variables(lbody_in, loop_locals(l));
682  else
683  global_in = effects_dup(lbody_in);
684 
685  pips_debug_effects(4, "initial IN(i)= \n", global_in);
686 
687  /* COMPUTATION OF INVARIANT IN EFFECTS */
688 
689  /* We get the loop transformer, which gives the loop invariant */
690  /* We must remove the loop index from the list of modified variables */
691  loop_trans = (*load_transformer_func)(current_stat);
692  loop_trans = transformer_remove_variable_and_dup(loop_trans, i);
693 
694  /* And we compute the invariant IN effects. */
695  // functions that can be pointed by effects_transformer_composition_op:
696  // effects_composition_with_transformer_nop
697  // effects_undefined_composition_with_transformer
698  // convex_regions_transformer_compose
699  // simple_effects_composition_with_effect_transformer
700  (*effects_transformer_composition_op)(global_in, loop_trans);
702 
703  pips_debug_effects(4, "invariant IN(i)= \n", global_in);
704 
705  /* OPTIMIZATION : */
706  /* If there is no write effect on a variable imported by the loop body,
707  * then, the same effect is imported by the whole loop.
708  */
709  /* Fix me: This may not be valid if there are effects on abstract locations.
710  */
711  global_in_read_only =
713  effects_dup(global_write),
715  global_in =
717  effects_dup(global_write),
719 
720  pips_debug_effects(4, "reduced IN(i)= \n", global_in);
721 
722  if (!ENDP(global_in))
723  {
724  // functions that can be pointed by loop_descriptor_make_func:
725  // loop_undefined_descriptor_make
726  // loop_convex_descriptor_make
727  // WIP
728  (*loop_range_in_effect_func)(l, &global_in, &global_write,
729  r_w_combinable_p, &i, r);
730  }
731 
732  /* we project the read_only regions along the actual loop index i */
733  // functions that can be pointed by effects_union_over_range_op:
734  // effects_union_over_range_nop
735  // simple_effects_union_over_range
736  // convex_regions_union_over_range
737  global_in_read_only =
738  (*effects_union_over_range_op)(global_in_read_only, loop_index(l),
740 
741  global_in = gen_nconc(global_in, global_in_read_only);
742 
743  /* we remove the write effects from the proper regions of the loop */
744  // functions that can be pointed by effects_sup_difference_op:
745  // effects_undefined_binary_operator
746  // RegionsSupDifference
747  // EffectsSupDifference
748  l_in = (*effects_sup_difference_op)(
749  global_in, l_prop_write, r_w_combinable_p);
750 
751  /* we merge these regions with the proper in regions of the loop */
752  // functions that can be pointed by effects_union_op:
753  // ProperEffectsMustUnion
754  // RegionsMustUnion
755  // ReferenceUnion
756  // EffectsMustUnion
757  l_in = (*effects_union_op)(l_in, l_prop_read, effects_same_action_p);
758 
759  store_in_effects_list(current_stat,l_in);
760  debug_consistent(l_in);
761 
762  pips_debug(1, "end\n");
763 }
764 
765 
766 static list
767 in_effects_of_external(entity func, list real_args)
768 {
769  list le = NIL;
770  const char *func_name = module_local_name(func);
772 
773  pips_debug(4, "translating effects for %s\n", func_name);
774 
775  if (! entity_module_p(func))
776  {
777  pips_internal_error("%s: bad function", func_name);
778  }
779  else
780  {
781  list func_eff;
783 
784  /* Get the in summary effects of "func". */
785  func_eff = (*db_get_summary_in_effects_func)(func_name);
786  /* Translate them using context information. */
787  context = (*load_context_func)(current_stat);
789  (func, real_args, func_eff, context);
790  }
791  return le;
792 }
793 
794 static bool written_before_read_p(entity ent,list args)
795 {
797  {
798  /* an argument in a READ statement can be a reference or an implied-DO call*/
800  MAP(REFERENCE,ref,
801  {
803  if (same_entity_p(e,ent))
804  {
805  /* the variable is in the reference list, check if it is written or read*/
807  {
809  if (reference_scalar_p(r))
810  return true;
811  return false;
812  }
813  return false;
814  }
815  },l);
816  },args);
817 
818  return false;
819 }
820 
821 
822 static void
823 in_effects_of_call(call c, in_effects_context *ctxt)
824 {
826 
827  list l_in = NIL;
828  entity e = call_function(c);
829  tag t = value_tag(entity_initial(e));
830  const char* n = module_local_name(e);
831 
832  list pc = call_arguments(c);
833 
834  pips_debug(1, "begin\n");
835  ifdebug(3)
836  {
837  pips_debug(3, "for current statement \n");
838  print_statement(current_stat);
839  }
840  switch (t) {
841  case is_value_constant:
842  pips_debug(5, "constant %s\n", n);
843  /* consnant have no in effects, do they ? */
844  break;
845  case is_value_code:
846  pips_debug(5, "external function %s\n", n);
847  l_in = in_effects_of_external(e, pc);
848  debug_consistent(l_in);
849  l_in = proper_to_summary_effects(l_in);
850  debug_consistent(l_in);
851  break;
852 
853  case is_value_intrinsic:
854  pips_debug(5, "intrinsic function %s\n", n);
855  debug_consistent(l_in);
856  list l_rw = convert_rw_effects(load_rw_effects_list(current_stat), ctxt);
857  debug_consistent(l_rw);
858  ifdebug(2){
859  pips_debug(2, "R/W effects: \n");
860  (*effects_prettyprint_func)(l_rw);
861  }
862 
863  l_in = effects_read_effects_dup(l_rw);
864  reset_converted_rw_effects(&l_rw, ctxt);
865 
866  /* Nga Nguyen 25/04/2002 : what about READ *,NDIM,(LSIZE(N), N=1,NDIM) ?
867  * Since NDIM is written before read => no IN effect on NDIM.
868  *
869  * So I add tests for the READ statement case. But this is only true for scalar variables :-)
870  *
871  * READ *,M,N,L,A(M*N),B(A(L)) ==> MAY-IN A ???*/
872 
873  if (strcmp(entity_local_name(e),READ_FUNCTION_NAME)==0)
874  {
875  list args = call_arguments(c);
876  pips_debug(5, " READ function\n");
877  MAP(EFFECT,reg,
878  {
879  entity ent = effect_entity(reg);
880  if (entity_scalar_p(ent) && written_before_read_p(ent,args))
881  gen_remove(&l_in,reg);
882  },l_in);
883  }
884 
885  debug_consistent(l_in);
886  break;
887 
888  default:
889  pips_internal_error("unknown tag %d", t);
890  break;
891  }
892 
893  ifdebug(2){
894  pips_debug(2, "IN effects: \n");
895  (*effects_prettyprint_func)(l_in);
896  }
897 
898  store_in_effects_list(current_stat,l_in);
899  debug_consistent(l_in);
900 
901  pips_debug(1, "end\n");
902 }
903 
904 /* Just to handle one kind of instruction, expressions which are not
905  calls. As we do not distinguish between Fortran and C, this
906  function is called for Fortran module although it does not have any
907  effect.
908  */
909 static void in_effects_of_expression_instruction(instruction i, in_effects_context *ctxt)
910 {
911  //list l_proper = NIL;
913  //instruction inst = statement_instruction(current_stat);
914  pips_debug(2, "begin for expression instruction in statement%03zd\n",
915  statement_ordering(current_stat));
916 
917  /* Is the call an instruction, or a sub-expression? */
919  {
920  list lrw = convert_rw_effects(load_rw_effects_list(current_stat), ctxt);
921  list lin = effects_read_effects_dup(lrw);
922  reset_converted_rw_effects(&lrw, ctxt);
923  store_in_effects_list(current_stat, lin);
924  }
925 
926  pips_debug(2, "end for expression instruction in statement%03zd\n",
927  statement_ordering(current_stat));
928 
929 }
930 
931 
932 static void
933 in_effects_of_unstructured(unstructured u, _UNUSED_ in_effects_context *ctxt)
934 {
936  list blocs = NIL ;
937  control ct;
938  list l_in = NIL, l_tmp = NIL;
939 
940  pips_debug(1, "begin\n");
941 
942  ct = unstructured_control( u );
943 
944  if(control_predecessors(ct) == NIL && control_successors(ct) == NIL)
945  {
946  /* there is only one statement in u; */
947  pips_debug(6, "unique node\n");
949  }
950  else
951  {
952  transformer t_unst = (*load_transformer_func)(current_stat);
953  CONTROL_MAP(c,
954  {
956  // functions that can be pointed by effects_test_union_op:
957  // EffectsMayUnion
958  // RegionsMayUnion
959  // ReferenceTestUnion
960  l_in = (*effects_test_union_op) (l_in, effects_dup(l_tmp),
962  },
963  ct, blocs) ;
964  // functions that can be pointed by effects_transformer_composition_op:
965  // effects_composition_with_transformer_nop
966  // effects_undefined_composition_with_transformer
967  // convex_regions_transformer_compose
968  // simple_effects_composition_with_effect_transformer
969  (*effects_transformer_composition_op)(l_in, t_unst);
971 
972  gen_free_list(blocs) ;
973  }
974 
975  store_in_effects_list(current_stat, l_in);
976  debug_consistent(l_in);
977  pips_debug(1, "end\n");
978 }
979 
980 
981 static void
982 in_effects_of_module_statement(statement module_stat, in_effects_context *ctxt)
983 {
985 
986  pips_debug(1,"begin\n");
987 
989  module_stat, ctxt,
990  statement_domain, in_effects_stmt_filter, in_effects_of_statement,
991  sequence_domain, gen_true, in_effects_of_sequence,
992  test_domain, gen_true, in_effects_of_test,
993  call_domain, gen_true, in_effects_of_call,
994  loop_domain, gen_true, in_effects_of_loop,
995  whileloop_domain, gen_true, in_effects_of_whileloop,
996  forloop_domain, gen_true, in_effects_of_forloop,
997  unstructured_domain, gen_true, in_effects_of_unstructured,
998  /* Just to retrieve effects of instructions with kind
999  * expression since they are ruled out by the next clause */
1000  instruction_domain, gen_true, in_effects_of_expression_instruction,
1001  expression_domain, gen_false, gen_null, /* NOT THESE CALLS */
1002  NULL);
1003 
1004  pips_debug(1,"end\n");
1006 }
1007 
1008 
1009 /* bool in_regions(const char* module_name):
1010  * input : the name of the current module.
1011  * requires : that transformers and precondition maps be set if needed.
1012  * (it depends on the chosen instanciation of *load_context_func
1013  * and *load_transformer_func).
1014  * output : nothing !
1015  * modifies :
1016  * comment : computes the in effects of the current module.
1017  */
1018 bool in_effects_engine(const char * module_name, effects_representation_val representation)
1019 {
1020  statement module_stat;
1023 
1024  /* Get the code of the module. */
1026  db_get_memory_resource(DBR_CODE, module_name, true) );
1027  module_stat = get_current_module_statement();
1028  make_statement_global_stack(); // for calls to semantics libray
1029 
1030  // functions that can be pointed by effects_computation_init_func:
1031  // effects_computation_no_init
1032  // init_convex_in_out_regions
1033  // init_convex_rw_regions
1034  (*effects_computation_init_func)(module_name);
1035 
1036  debug_on("IN_EFFECTS_DEBUG_LEVEL");
1037  pips_debug(1, "begin for module %s\n", module_name);
1038 
1039  /* set necessary effects maps */
1043 
1044  /* initialise the maps for in regions */
1045  init_in_effects();
1048 
1049  /* Compute the effects of the module. */
1050  in_effects_context ctxt;
1051  init_in_effects_context(&ctxt, representation);
1052  in_effects_of_module_statement(module_stat, &ctxt);
1053  reset_in_effects_context(&ctxt);
1054 
1055  /* Put computed resources in DB. */
1056  (*db_put_in_effects_func)
1058  (*db_put_invariant_in_effects_func)
1060  (*db_put_cumulated_in_effects_func)
1062 
1063  pips_debug(1, "end\n");
1064 
1065  debug_off();
1066 
1069  free_statement_global_stack(); // for calls to semantics libray
1070 
1071  reset_rw_effects();
1074 
1075  reset_in_effects();
1078 
1079  // functions that can be pointed by effects_computation_reset_func:
1080  // effects_computation_no_reset
1081  // reset_convex_in_out_regions
1082  // reset_convex_rw_regions
1083  (*effects_computation_reset_func)(module_name);
1084 
1086 
1087  return true;
1088 }
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
list l_inst
The list "first" is a truncated list from the first to the current statement (not included).
Definition: atomizer.h:87
#define pips_debug_effects(level, message, l_eff)
effects_representation_val
void free_effects_private_current_context_stack(void)
list effects_store_effects(list)
list load_invariant_rw_effects_list(statement)
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 make_effects_private_current_context_stack(void)
void init_cumulated_in_effects(void)
transformer(* load_context_func)(statement)
void make_effects_private_current_stmt_stack(void)
utils.c
bool in_effects_engine(const char *, effects_representation_val)
void store_in_effects_list(statement, list)
list proper_to_summary_effects(list)
void init_invariant_in_effects(void)
list effects_read_effects(list)
void reset_cumulated_in_effects(void)
statement_effects(* db_get_invariant_rw_effects_func)(const char *)
list effects_write_effects_dup(list)
bool summary_in_effects_engine(const char *)
in_effects_engine.c
list load_proper_rw_effects_list(statement)
statement_effects get_cumulated_in_effects(void)
transformer transformer_remove_variable_and_dup(transformer, entity)
statement effects_private_current_stmt_pop(void)
list effects_entities_inf_difference(list, list, bool(*)(effect, effect))
void store_invariant_in_effects_list(statement, list)
statement_effects get_invariant_in_effects(void)
void reset_proper_rw_effects(void)
void free_effects_private_current_stmt_stack(void)
void set_proper_rw_effects(statement_effects)
void effects_free(list)
list generic_effects_backward_translation(entity, list, list, transformer)
list load_in_effects_list(statement)
statement effects_private_current_stmt_head(void)
void effects_private_current_stmt_push(statement)
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)
list effects_entities_intersection(list, list, bool(*)(effect, effect))
bool get_constant_paths_p(void)
statement_effects get_in_effects(void)
void store_cumulated_in_effects_list(statement, list)
list effects_write_effects(list)
list generic_proper_effects_of_expression(expression)
void reset_invariant_rw_effects(void)
statement_effects(* db_get_in_effects_func)(const char *)
transformer effects_private_current_context_pop(void)
bool r_w_combinable_p(effect, effect)
void effects_private_current_context_push(transformer)
list effects_dup_without_variables(list, list)
list pointer_effects_to_constant_path_effects(list)
void set_invariant_rw_effects(statement_effects)
statement_effects(* db_get_proper_rw_effects_func)(const char *)
void reset_rw_effects(void)
void init_in_effects(void)
bool effects_same_action_p(effect, effect)
void update_invariant_in_effects_list(statement, list)
statement_effects(* db_get_rw_effects_func)(const char *)
entity effect_entity(effect)
cproto-generated files
Definition: effects.c:52
#define descriptor_undefined
Definition: effects.h:559
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
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....
void gen_full_free_list(list l)
Definition: genClib.c:1023
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an 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
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
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
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
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
static void reset_converted_rw_effects(list *lrw, live_paths_analysis_context *ctxt)
static list convert_rw_effects(list lrw, live_paths_analysis_context *ctxt)
#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_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
const char * entity_minimal_name(entity e)
Do preserve scope informations.
Definition: naming.c:214
int tag
TAG.
Definition: newgen_types.h:92
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
string string_of_type(const type)
Definition: type.c:56
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
void set_bool_property(const char *, bool)
#define READ_FUNCTION_NAME
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
bool static_area_p(entity aire)
Definition: area.c:77
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
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
bool entity_module_p(entity e)
Definition: entity.c:683
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
bool reference_scalar_p(reference r)
This function returns true if Reference r is scalar.
Definition: expression.c:3530
list expression_to_reference_list(expression e, list lr)
conversion of an expression into a list of references; references are appended to list lr as they are...
Definition: expression.c:1263
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
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 value_tag(x)
Definition: ri.h:3064
#define loop_body(x)
Definition: ri.h:1644
#define test_domain
newgen_entity_domain_defined
Definition: ri.h:418
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define transformer_undefined
Definition: ri.h:2847
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#define call_function(x)
Definition: ri.h:709
#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
@ is_value_intrinsic
Definition: ri.h:3034
@ is_value_constant
Definition: ri.h:3033
@ is_value_code
Definition: ri.h:3031
#define storage_ram_p(x)
Definition: ri.h:2519
#define instruction_domain
newgen_functional_domain_defined
Definition: ri.h:202
#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 expression_undefined
Definition: ri.h:1223
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define control_successors(x)
Definition: ri.h:945
#define loop_locals(x)
Definition: ri.h:1650
#define expression_undefined_p(x)
Definition: ri.h:1224
#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 entity_type(x)
Definition: ri.h:2792
#define value_expression_p(x)
Definition: ri.h:3080
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
#define evaluation_before_p(x)
Definition: ri.h:1159
#define type_variable_p(x)
Definition: ri.h:2947
#define value_expression(x)
Definition: ri.h:3082
#define loop_index(x)
Definition: ri.h:1640
#define instruction_expression_p(x)
Definition: ri.h:1539
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
#define ifdebug(n)
Definition: sg.c:47
static size_t current
Definition: string.c:115
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: delay.c:253
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207