PIPS
privatize.c
Go to the documentation of this file.
1 /*
2  $Id: privatize.c 23495 2018-10-24 09:19:47Z coelho $
3 
4  Copyright 1989-2016 MINES ParisTech
5 
6  This file is part of PIPS.
7 
8  PIPS is free software: you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  any later version.
12 
13  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
14  WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  FITNESS FOR A PARTICULAR PURPOSE.
16 
17  See the GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 // do not compile unless required
25 #include "phases.h"
26 #if defined(BUILDER_PRIVATIZE_MODULE) || \
27  defined(BUILDER_PRIVATIZE_MODULE_EVEN_GLOBALS) || \
28  defined(BUILDER_LOCALIZE_DECLARATIONS)
29 
30 #ifdef HAVE_CONFIG_H
31 #include "pips_config.h"
32 #endif
33 /* -- privatize.c
34 
35  This algorithm introduces local definitions into loops that are
36  kennedizable. The privatization is only performed on dynamic scalar
37  variables (could be extended to STACK variables, but why would you
38  allocate a variable in the PIPS *STACK* area). It is based on the
39  dependence levels. The variable can only be private to loops
40  containing all dependence arcs related to the variable. This should
41  fail in C when a dynamic variable is initialized.
42 
43 */
44 #include <stdio.h>
45 #include <string.h>
46 
47 #include "genC.h"
48 #include "linear.h"
49 
50 #include "misc.h"
51 #include "pipsdbm.h"
52 #include "properties.h"
53 
54 #include "ri.h"
55 #include "ri-util.h"
56 #include "text-util.h"
57 #include "prettyprint.h"
58 
59 #include "effects.h"
60 #include "effects-util.h" // used
61 
62 #include "dg.h" // used
63 #include "control.h" // clean_up_sequences, module_reorder
64 
65 #include "effects-generic.h" // used
66 #include "effects-simple.h" // used
67 
68 #include "transformations.h" // module_clean_declarations in "declarations.c"
69 
70 /* instantiation of the dependence graph */
71 typedef dg_arc_label arc_label;
73 
74 #include "graph.h"
75 
76 typedef struct {
77  entity e;
78  bool loop_index_p;
79  bool used_through_external_calls;
80 } privatizable_ctxt;
81 
82 static bool loop_in(loop l, privatizable_ctxt *ctxt)
83 {
84  if (loop_index(l) == ctxt->e)
85  ctxt->loop_index_p = true;
86  return ctxt->loop_index_p;
87 }
88 
89 static bool call_in(call c, privatizable_ctxt *ctxt)
90 {
91  entity func = call_function(c);
92  const char* func_name = module_local_name(func);
93  type uet = ultimate_type(entity_type(func));
94 
95  pips_debug(4, "begin for %s\n", entity_local_name(func));
96 
97  if(type_functional_p(uet))
98  {
99  if (value_code_p(entity_initial(func)))
100  {
101  pips_debug(4, "external function\n");
102  /* Get the summary effects of "func". */
103  list func_eff = (*db_get_summary_rw_effects_func)(func_name);
104  /* tests if the function may refer to the global variable */
105  list l_conflicts = effects_entities_which_may_conflict_with_scalar_entity(func_eff, ctxt->e);
106  if (!ENDP(l_conflicts))
107  {
108  ctxt->used_through_external_calls = true;
109  gen_free_list(l_conflicts);
110  }
111  }
112  // else
113  // nothing to do
114  }
115  else if(type_variable_p(uet))
116  {
117  pips_debug(4, "function called through pointer -> assume worst case\n");
118  ctxt->used_through_external_calls = true;
119  }
120 
121  return (!ctxt->used_through_external_calls);
122 }
123 
124 /* privatizable() checks whether the entity e is privatizable in statement s. */
125 static bool entity_privatizable_in_loop_statement_p(
126  entity e, statement stmt, bool even_globals)
127 {
128  storage s = entity_storage( e ) ;
129  bool result = entity_scalar_p(e);
130  loop l = statement_loop(stmt);
131 
132  ifdebug(4)
133  {
134  pips_debug(4, "begin for statement: \n");
136  }
137 
138  /* For C, it should be checked that e has no initial value because
139  there is no dependence arc between the initialization in t he
140  declaration and the other references. This is not very smart,
141  because it all depends on where e is declared.
142 
143  FI: OK, I removed this safety test because declarations now
144  have effects and are part of the use-def chains
145 
146  Also, stack_area_p() would be OK for a privatization.
147  */
148 
149  pips_debug(3, "checking entity %s, with storage %s \n", entity_name(e), storage_to_string(s));
150 
151  /* Since there is currently no variable liveness analysis, we
152  cannot privatize global variables. However, we consider that
153  inner loop indices are privatizable to allow correct
154  parallelization of outer loops
155  */
156  if (result && even_globals
158  && top_level_entity_p(e) )
159  {
160  pips_debug(3, "global variable\n");
161 
162  /* check that the value of e is not re-used outside the loop */
163  list l_live_out = load_live_out_paths_list(stmt);
164  list l_conflicts_out = effects_entities_which_may_conflict_with_scalar_entity(l_live_out, e);
165  list l_live_in = load_live_in_paths_list(stmt);
166  list l_conflicts_in = effects_entities_which_may_conflict_with_scalar_entity(l_live_in, e);
167 
168  if (ENDP(l_conflicts_out) && ENDP(l_conflicts_in))
169  {
170  privatizable_ctxt ctxt = {e, false, false};
171  /* check that e is not used through called functions */
172  /* It may be passed to a function as a parameter,
173  but it must not be used as a global variable */
174  gen_context_multi_recurse(loop_body(l), &ctxt, call_domain, call_in, gen_null, NULL);
175  result = !ctxt.used_through_external_calls;
176  }
177  else
178  {
179  gen_free_list(l_conflicts_out);
180  gen_free_list(l_conflicts_in);
181  result = true;
182  }
183  }
184 
185  /* Here is the old behavior, to be removed when the
186  previous if branch has been sufficiently tested */
187  else if (result && !even_globals && c_module_p(get_current_module_entity())
189  && top_level_entity_p( e) /* this test may be removed since we check that e is used as a loop index */)
190  {
191  privatizable_ctxt ctxt = {e, false, false};
192  /* check if e is an internal loop index */
193  gen_context_recurse(loop_body(l), &ctxt, loop_domain, loop_in, gen_null2);
194  result = ctxt.loop_index_p;
195  }
196  else
197  {
198  result = result &&
201  }
202  pips_debug(3, "returning %s\n", bool_to_string(result));
203  return(result);
204 }
205 
206 /* SCAN_STATEMENT gathers the list of enclosing LOOPS of statement S.
207  Moreover, the locals of loops are initialized to all possible
208  private entities. */
209 
210 static void scan_unstructured(unstructured u, list loops, bool even_globals) ;
211 
212 static void scan_statement(statement s, list loops, bool even_globals)
213 {
215 
218  }
220 
221  switch(instruction_tag(i)) {
223  MAPL(ps, {scan_statement(STATEMENT(CAR(ps)), loops, even_globals);},
224  instruction_block(i));
225  break ;
226  case is_instruction_loop: {
227  loop l = instruction_loop(i);
228  statement b = loop_body(l);
229  list new_loops =
231  list locals = NIL ;
232 
234  entity e = effect_entity( f ) ;
235 
236  if(!anywhere_effect_p(f)
238  && entity_privatizable_in_loop_statement_p( e, s, even_globals)
239  && gen_find_eq( e, locals ) == entity_undefined ) {
240  locals = CONS( ENTITY, e, locals ) ;
241  }
242  }
243 
244  /* Add the loop index if it's privatizable because it does not have to be taken
245  into account for parallelization. */
246  //if (entity_privatizable_in_loop_statement_p( loop_index(l), s, even_globals))
247  loop_locals( l ) = CONS( ENTITY, loop_index( l ), locals ) ;
248 
249  /* FI: add the local variables of the loop body at least, but
250  they might have to be added recursively for all enclosed
251  loops. Note: their dependency pattern should lead to
252  privatization, but they are eliminated from the body
253  effect and not taken into consideration. */
256 
257  scan_statement( b, new_loops, even_globals ) ;
258  hash_del(get_enclosing_loops_map(), (char *) s) ;
259  store_statement_enclosing_loops(s, new_loops);
260  break;
261  }
262  case is_instruction_test: {
263  test t = instruction_test( i ) ;
264 
265  scan_statement( test_true( t ), loops, even_globals ) ;
266  scan_statement( test_false( t ), loops, even_globals ) ;
267  break ;
268  }
271  statement b = whileloop_body(l);
272  scan_statement(b, loops, even_globals ) ;
273  break;
274  }
275  case is_instruction_forloop: {
277  statement b = forloop_body(l);
278  scan_statement(b, loops, even_globals ) ;
279  break;
280  }
282  scan_unstructured( instruction_unstructured( i ), loops, even_globals ) ;
283  break ;
284  case is_instruction_call:
286  case is_instruction_goto:
287  break ;
288  default:
289  pips_internal_error("unexpected tag %d", instruction_tag(i));
290  }
291 }
292 
293 static void scan_unstructured(unstructured u, list loops, bool even_globals)
294 {
295  list blocs = NIL ;
296 
297  CONTROL_MAP( c, {scan_statement( control_statement( c ), loops, even_globals );},
298  unstructured_control( u ), blocs ) ;
299  gen_free_list( blocs ) ;
300 }
301 
302 /* UPDATE_LOCALS removes the entity E from the locals of loops in LS that
303  are not in common with the PREFIX. */
304 
305 static void update_locals(list prefix, list ls, entity e)
306 {
307  pips_debug(1, "Begin\n");
308 
309  if( ENDP( prefix )) {
310  if(!ENDP(ls)) {
311  ifdebug(1) {
312  pips_debug(1, "Removing %s from locals of ", entity_name( e )) ;
313  FOREACH(STATEMENT, st, ls) {
314  pips_debug(1, "%td ", statement_number( st )) ;
315  }
316  pips_debug(1, "\n" ) ;
317  }
318  FOREACH(STATEMENT, st, ls) {
320 
321  pips_assert( "instruction i is a loop", instruction_loop_p( i )) ;
323  pips_debug(1, "Variable %s is removed from locals of statement %td\n",
324  entity_name(e), statement_number(st));
325  }
326  }
327  else {
328  pips_debug(1, "ls is empty, end of recursion\n");
329  }
330  }
331  else {
332  pips_assert( "The first statements in prefix and in ls are the same statement",
333  STATEMENT( CAR( prefix )) == STATEMENT( CAR( ls ))) ;
334 
335  pips_debug(1, "Recurse on common prefix\n");
336 
337  update_locals( CDR( prefix ), CDR( ls ), e ) ;
338  }
339 
340  pips_debug(1, "End\n");
341 }
342 
343 /* TRY_PRIVATIZE knows that the effect F on entity E is performed in
344  the statement ST of the vertex V of the dependency graph. Arrays
345  are not privatized. */
346 
347 static void try_privatize(vertex v, statement st, effect f, entity e)
348 {
349  list ls ;
350 
351  /* BC : really dirty : overrides problems in the computation of
352  effects for C programs; Should be fixed later. */
353  if (anywhere_effect_p(f))
354  {return;}
355 
356  /* Only scalar entities can be privatized */
357  if( !entity_scalar_p( e )) {
358  return ;
359  }
360 
361  /* Only program variables can be privatized. This test may not be
362  strong enough to guarantee that e is a program variable */
363  if(!entity_variable_p(e)) {
364  return;
365  }
366 
368 
369  ifdebug(1) {
370  if(statement_loop_p(st)) {
371  pips_debug(1, "Trying to privatize %s in loop statement %td (ordering %03zd) with local(s) ",
374  }
375  else {
376  pips_debug(1, "Trying to privatize %s in statement %td\n",
377  entity_local_name( e ), statement_number( st )) ;
378  }
379  }
380 
381  FOREACH(SUCCESSOR, succ, vertex_successors(v)) {
382  vertex succ_v = successor_vertex( succ ) ;
383  dg_vertex_label succ_l =
385  dg_arc_label arc_l =
387  statement succ_st =
389  instruction succ_i = statement_instruction( succ_st ) ;
390  list succ_ls = load_statement_enclosing_loops( succ_st ) ;
391 
392  /* this portion of code induced the erroneous privatization of
393  non-private variables, for instance in :
394 
395  DO I = 1,10
396  J = J +1
397  a(I) = J
398  ENDDO
399 
400  so I comment it out. But some loops are not parallelized
401  anymore for instance Semantics/choles, Ricedg/private and
402  Prettyprint/matmul. (see ticket #152). BC.
403 
404  In fact, J is privatizable in the above loop if J is not
405  initialized. We have to remember that PIPS maintains the
406  semantics of well-defined code, but correctly output weird
407  results when it does not matter. We also have to remember that
408  a PIPS phase that has been used for almost 20 years is unlikely
409  to be buggy with Fortran code. For C code, careful extensions
410  might be needed: in this case, dynamic variables can be
411  initialized and the initialization is not taken into account by
412  the dependence graph (for the time being). Hence function
413  "privatizable" was made a bit mor restrictive.
414 
415  The test commented out is correct, but not explained. SO I
416  chose to change the behavior at a lower level, where it is
417  easier to understand. Ticket #152 should probably be
418  closed. FI.
419  */
420  /*
421  if( v == succ_v) {
422  continue ;
423  }
424  */
425 
427  effect sc = conflict_source( c ) ;
428  effect sk = conflict_sink( c ) ;
429 
430  if(store_effect_p(sc)) {
431  /* Only store effects are considered for privatization */
433 
434  pips_assert("Both effects sc and sk are of the same kind",
435  store_effect_p(sk));
436 
437  /* Take into account def-def and use-def arcs only */
438  if(!entities_may_conflict_p( e, effect_entity( sc )) ||
440  action_write_p( effect_action( sk))) {
441  continue ;
442  }
443  /* PC dependance and the sink is a loop index */
444  if(action_read_p( effect_action( sk )) &&
445  (instruction_loop_p( succ_i) ||
446  is_implied_do_index( e, succ_i))) {
447  continue ;
448  }
449  pips_debug(5,"Conflict for %s between statements %td and %td\n",
451  statement_number(st),
452  statement_number(succ_st));
453 
454  if (v==succ_v) {
455  /* No decision can be made from this couple of effects alone */
456  ;
457  //pips_debug(5,"remove %s from locals in all enclosing loops\n",
458  // entity_local_name(e));
459  //update_locals( NIL, ls, e ); /* remove e from all enclosing loops */
460  }
461  else {
462  pips_debug(5,"remove %s from locals in non common enclosing loops\n",
463  entity_local_name(e));
464  prefix = gen_common_prefix( ls, succ_ls ) ;
465  /* e cannot be a local variable at a lower level than
466  the common prefix because of this dependence
467  arc. */
468  update_locals( prefix, ls, e ) ;
469  update_locals( prefix, succ_ls, e ) ;
470  gen_free_list( prefix ) ;
471  }
472  }
473  }
474  }
475 
476  pips_debug(1, "End\n");
477 }
478 
479 /* PRIVATIZE_DG looks for definition of entities that are locals to the loops
480  in the dependency graph G for the control graph U. */
481 
482 static bool generic_privatize_module(string mod_name, bool even_globals)
483 {
484  entity module;
486  graph mod_graph;
487 
490 
492  db_get_memory_resource(DBR_CODE, mod_name, true) );
494 
496  db_get_memory_resource(DBR_PROPER_EFFECTS, mod_name, true));
497 
499  db_get_memory_resource(DBR_CUMULATED_EFFECTS, mod_name, true) );
500 
501  if (even_globals)
502  {
503  set_constant_paths_p(true);
506  set_methods_for_live_paths(mod_name);
509  }
510 
511  mod_graph = (graph)
512  db_get_memory_resource(DBR_CHAINS, mod_name, true);
513 
514  debug_on("PRIVATIZE_DEBUG_LEVEL");
515  pips_debug(1, "\n begin for module %s\n\n", mod_name);
517 
518  /* Set the prettyprint language for debug */
520  if(value_code_p(mv)) {
521  code c = value_code(mv);
523  } else {
524  /* Should never arise */
526  }
527 
528  /* Build maximal lists of private variables in loop locals */
529  /* scan_unstructured(instruction_unstructured(mod_inst), NIL); */
530  scan_statement(mod_stat, NIL, even_globals);
531 
532  /* remove non private variables from locals */
533  FOREACH(VERTEX, v, graph_vertices( mod_graph )) {
535  statement st =
537 
538  pips_debug(1, "Entering statement %03zd :\n", statement_ordering(st));
539  ifdebug(4) {
540  print_statement(st);
541  }
542 
544  entity e = effect_entity( f ) ;
545  ifdebug(4) {
546  pips_debug(1, "effect :");
547  print_effect(f);
548  }
549  if( action_write_p( effect_action( f ))) {
550  try_privatize( v, st, f, e ) ;
551  }
552  }
553  }
554 
555  /* sort locals
556  */
558 
559  debug_off();
560  DB_PUT_MEMORY_RESOURCE(DBR_CODE, mod_name, mod_stat);
561  DB_PUT_FILE_RESOURCE(DBR_PRIVATIZED, mod_name, strdup(""));
562 
567  if (even_globals)
568  {
571  }
572 
575 
576  return true;
577 }
578 
579 bool privatize_module(const string mod_name)
580 {
581  return generic_privatize_module(mod_name, false);
582 }
583 
584 bool privatize_module_even_globals(const string mod_name)
585 {
586  return generic_privatize_module(mod_name, true);
587 }
588 
589 
590 
591 /**
592  * @name localize declaration
593  * @{ */
594 
595 static void do_gather_loop_indices(loop l, set s) {
596  set_add_element(s,s,loop_index(l));
597 }
598 
599 static set gather_loop_indices(void *v) {
600  set s = set_make(set_pointer);
601  gen_context_recurse(v, s, loop_domain, gen_true2, do_gather_loop_indices);
602  return s;
603 }
604 
605 /**
606  * gen_recurse context for localize declaration, keep track of the scope !
607  */
608 #define MAX_DEPTH 100
609 typedef struct {
610  int depth;
611  int scope_numbers[MAX_DEPTH];
612  hash_table old_entity_to_new;
613 } localize_ctx;
614 
615 /**
616  * Create a context
617  */
618 static localize_ctx make_localize_ctx() {
619  localize_ctx ctx;
620  ctx.depth= -1;
621  memset(ctx.scope_numbers, -1, MAX_DEPTH*sizeof(ctx.scope_numbers[0]));
622  ctx.old_entity_to_new = hash_table_make(hash_pointer,HASH_DEFAULT_SIZE);
623 
624  return ctx;
625 }
626 
627 /**
628  * Keep track of the scope during recursion
629  */
630 static bool localize_track_scope_in(statement s, localize_ctx *ctx) {
631  if(statement_block_p(s)) {
632  pips_assert("depth is in acceptable range\n", ctx->depth<MAX_DEPTH);
633  ctx->depth++;
634  ctx->scope_numbers[ctx->depth]++;
635  }
636  return true;
637 }
638 
639 /**
640  * Keep track of the scope during recursion
641  */
642 static void localize_track_scope_out(statement s, localize_ctx *ctx) {
643  if(statement_block_p(s)) {
644  ctx->depth--;
645  }
646 }
647 
648 
649 /**
650  * Create an (unique) entity taking into account the current scope
651  */
652 static entity make_localized_entity(entity e, localize_ctx *ctx) {
653  const char * module_name = get_current_module_name();
654  string build_localized_name = strdup("");
655  for(int i=1;i<=ctx->depth;i++) {
656  string new_name;
657  asprintf(&new_name,"%s%d" BLOCK_SEP_STRING,build_localized_name,ctx->scope_numbers[i]);
658  free(build_localized_name);
659  build_localized_name = new_name;
660  }
661  string localized_name;
662  asprintf(&localized_name,"%s%s",build_localized_name, entity_user_name(e));
663  free(build_localized_name);
664 
665  string unique_name = strdup(localized_name);
666  int count = 0;
667  while(!entity_undefined_p(FindEntity(module_name,unique_name))) {
668  free(unique_name);
669  asprintf(&unique_name,"%s%d",localized_name, ++count);
670  pips_assert("infinite loop ?",count<10000);
671  }
672  free(localized_name);
673 
674  entity new_ent = FindOrCreateEntity(module_name,unique_name);
675  entity_type(new_ent)=copy_type(entity_type(e));
676  entity_initial(new_ent) = make_value_unknown();
677 
680 
681  type pvt = ultimate_type(entity_type(new_ent));
682  variable pvtv = type_variable(pvt);
683  basic pvb = variable_basic(pvtv);
684 
685  int offset = 0;
688  (add_C_variable_to_area(a, e)):(0);
689  else
691  (add_variable_to_area(a, e)):(0);
692 
694  make_ram(f, a, offset, NIL));
695 
696  return new_ent;
697 }
698 
699 
700 /**
701  * @brief Create a statement block around the statement if it is a do-loop with
702  * local/private variable
703  *
704  * It creates statement_blocks where needed to hold further declarations later
705  * And then performs localization based on the locals field
706  *
707  * @param s concerned statement
708  */
709 static void localize_declaration_walker(statement s, localize_ctx *ctx) {
710  if(statement_loop_p(s)) {
712  loop l = instruction_loop(i);
713 
714  /* create a new statement to hold the future private declaration SG:
715  as a side effect, pragmas on the loop are moved to the enclosing
716  block __this_is_usefull__ at least to me ^^
717  */
718  if(!ENDP(loop_locals(l))) {
719  /* Put the loop in a new statement block if there are loop-private variable(s): */
720  statement new_statement = instruction_to_statement(i);
721  instruction iblock = make_instruction_block(CONS(STATEMENT,new_statement,NIL));
722  statement_instruction(s) = iblock;
723  /* keep comments and extensions attached to the loop */
724  string stmp = statement_comments(s);
725  statement_comments(s)=statement_comments(new_statement);
726  statement_comments(new_statement)=stmp;
727 
728  extensions ex = statement_extensions(new_statement);
729  statement_extensions(new_statement) = statement_extensions(s);
730  statement_extensions(s) = ex;
731 
732  entity etmp = statement_label(s);
733  statement_label(s) = statement_label(new_statement);
734  statement_label(new_statement) = etmp;
735 
736  intptr_t itmp = statement_number(s);
737  statement_number(s) = statement_number(new_statement);
738  statement_number(new_statement) = itmp;
739 
740  /* now add declarations to the created block */
741  list locals = gen_copy_seq(loop_locals(l));
743  set li = gather_loop_indices(s);
744  bool skip_loop_indices = get_bool_property("LOCALIZE_DECLARATION_SKIP_LOOP_INDICES");
745 
746  // take into account that we are in a new block
747  localize_track_scope_in(s,ctx);
748  pips_debug(1,"Handling a loop with scope (%d,%d)",ctx->depth,ctx->scope_numbers[ctx->depth]);
749 
750  FOREACH(ENTITY,e,locals)
751  {
752  if(!entity_in_list_p(e,sd)
753  && !same_entity_p(e,loop_index(l)) // do not localize this one, or initialize its value!
754  && !(skip_loop_indices && set_belong_p(li,e))) {
755  /* create a new name for the local entity */
756  entity new_entity = make_localized_entity(e,ctx);
757  pips_debug(1,"Creating localized entity : %s (from %s)\n",entity_name(new_entity), entity_name(e));
758  /* get the new entity and initialize it and register it*/
759  /* add the variable to the loop body if it's not an index */
761 
762  list previous_replacements = hash_get(ctx->old_entity_to_new,e);
763  if( previous_replacements == HASH_UNDEFINED_VALUE )
764  previous_replacements = CONS(ENTITY,new_entity,NIL);
765  previous_replacements=gen_nconc(previous_replacements,CONS(ENTITY,e,NIL));
766  hash_put(ctx->old_entity_to_new,e,previous_replacements);
767  FOREACH(ENTITY,prev,previous_replacements) {
768  replace_entity(s,prev,new_entity);
769  }
770  }
771  }
772 
773  // take into account that we exit a block
774  localize_track_scope_out(s,ctx);
775 
776  set_free(li);
777  gen_free_list(locals);
778  gen_free_list(sd);
779  }
780  } else {
781  localize_track_scope_out(s, ctx);
782  }
783 
784 }
785 
786 /**
787  * @brief make loop local variables declared in the innermost statement
788  *
789  * @param mod_name name of the module being processed
790  *
791  * @return
792  */
793 bool localize_declaration(const string mod_name)
794 {
795  /* prelude */
796  debug_on("LOCALIZE_DECLARATION_DEBUG_LEVEL");
797  pips_debug(1,"begin localize_declaration ...\n");
800  (statement) db_get_memory_resource(DBR_CODE, mod_name, true) );
801 
802  /* Propagate local informations to loop statements */
803 
804  // To keep track of what has been done:
805  ifdebug(1) {
806  pips_debug(1,"The statement before we create block statement:\n");
808  }
809 
810  // Create the statement_block where needed and perform localization
812 
813  // Context for recursion
814  localize_ctx ctx = make_localize_ctx();
815 
817  statement_domain, localize_track_scope_in, localize_declaration_walker);
818 
819  ifdebug(1) {
820  pips_debug(1,"The statement before we convert loop_locals "
821  "to local declarations:\n");
823  }
824  // Use loop_locals data to fill local declarations:
826  hash_table_free(ctx.old_entity_to_new);
827 
828  ifdebug(1) {
829  pips_debug(1,"The statement after conversion:\n");
831  }
832 
833  /* Renumber the statement with a new ordering */
835 
836  /* postlude */
837  debug_off();
838 
839  /* Apply clean declarations ! */
840  debug_on("CLEAN_DECLARATIONS_DEBUG_LEVEL");
842  (statement_effects)db_get_memory_resource(DBR_CUMULATED_EFFECTS,
843  mod_name,
844  true));
848  debug_off();
849 
851 
854  pips_debug(1,"end localize_declaration\n");
855  return true;
856 }
857 
858 /** @} */
859 
860 #endif // BUILDER_*
value make_value_unknown(void)
Definition: ri.c:2847
type copy_type(type p)
TYPE.
Definition: ri.c:2655
storage make_storage(enum storage_utype tag, void *val)
Definition: ri.c:2273
ram make_ram(entity a1, entity a2, intptr_t a3, list a4)
Definition: ri.c:1999
static int count
Definition: SDG.c:519
dg_vertex_label vertex_label
Definition: delay.c:64
dg_arc_label arc_label
Definition: delay.c:63
bool clean_up_sequences(statement s)
Recursively clean up the statement sequences by fusing them if possible and by removing useless one.
static list loops
#define dg_vertex_label_statement(x)
Definition: dg.h:235
struct _newgen_struct_dg_arc_label_ * dg_arc_label
Definition: dg.h:60
#define conflict_sink(x)
Definition: dg.h:167
#define CONFLICT(x)
CONFLICT.
Definition: dg.h:134
#define dg_arc_label_conflicts(x)
Definition: dg.h:201
#define conflict_source(x)
Definition: dg.h:165
struct _newgen_struct_dg_vertex_label_ * dg_vertex_label
Definition: dg.h:68
static Value offset
Definition: translation.c:283
@ with_no_pointer_info
void set_live_in_paths(statement_effects)
void reset_live_out_paths(void)
list load_live_out_paths_list(statement)
statement_effects(* db_get_live_in_paths_func)(const char *)
list load_live_in_paths_list(statement)
statement_effects(* db_get_live_out_paths_func)(const char *)
list load_proper_rw_effects_list(statement)
void set_live_out_paths(statement_effects)
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
void set_cumulated_rw_effects(statement_effects)
list load_cumulated_rw_effects_list(statement)
void reset_live_in_paths(void)
void set_pointer_info_kind(pointer_info_val)
methods.c
void reset_cumulated_rw_effects(void)
void set_constant_paths_p(bool)
void set_methods_for_simple_effects(void)
bool is_implied_do_index(entity, instruction)
void set_methods_for_live_paths(const char *)
entity effect_entity(effect)
cproto-generated files
Definition: effects.c:52
bool store_effect_p(effect)
Definition: effects.c:1062
bool anywhere_effect_p(effect)
Is it an anywhere effect? ANYMMODULE:ANYWHERE
Definition: effects.c:346
#define effect_action(x)
Definition: effects.h:642
#define action_write_p(x)
Definition: effects.h:314
#define action_read_p(x)
Definition: effects.h:311
#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....
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
void free(void *)
#define successor_vertex(x)
Definition: graph.h:118
#define successor_arc_label(x)
Definition: graph.h:116
struct _newgen_struct_graph_ * graph
Definition: graph.h:31
#define vertex_vertex_label(x)
Definition: graph.h:152
#define vertex_successors(x)
Definition: graph.h:154
#define SUCCESSOR(x)
SUCCESSOR.
Definition: graph.h:86
#define graph_vertices(x)
Definition: graph.h:82
#define VERTEX(x)
VERTEX.
Definition: graph.h:122
bool entities_may_conflict_p(entity e1, entity e2)
Check if two entities may conflict.
Definition: conflicts.c:984
list effects_entities_which_may_conflict_with_scalar_entity(list fx, entity e)
Definition: conflicts.c:1273
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
#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
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
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 replace_entity(void *s, entity old, entity new)
per variable version of replace_entities.
Definition: replace.c:113
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
void clean_enclosing_loops(void)
Definition: loop.c:58
void sort_all_loop_locals(statement s)
Definition: loop.c:381
#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
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
list gen_common_prefix(const list l1, const list l2)
return the common list prefix of lists l1 and l2.
Definition: list.c:1033
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
void * gen_find_eq(const void *item, const list seq)
Definition: list.c:422
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
#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
#define DB_PUT_FILE_RESOURCE
Put a file resource into the current workspace database.
Definition: pipsdbm-local.h:85
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
bool statement_loop_p(statement)
Definition: statement.c:349
list statement_to_declarations(void *)
Get a list of all variables declared recursively within a statement.
Definition: statement.c:3253
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
void * hash_del(hash_table htp, const void *key)
this function removes from the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:439
static statement mod_stat
We want to keep track of the current statement inside the recurse.
Definition: impact_check.c:41
void set_prettyprint_language_from_property(enum language_utype native)
set the prettyprint language according to the property PRETTYPRINT_LANGUAGE @description If the prope...
Definition: language.c:103
void * memset(void *str, int c, size_t len)
memset.c – set an area of memory to a given value Copyright (C) 1991, 2003, 2009-2011 Free Software F...
Definition: memset.c:23
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define asprintf
Definition: misc-local.h:225
#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
#define DYNAMIC_AREA_LOCAL_NAME
Definition: naming-local.h:69
#define BLOCK_SEP_STRING
Scope separator.
Definition: naming-local.h:50
#define MAKE_STATEMENT_MAPPING()
Definition: newgen-local.h:43
string bool_to_string(bool)
Definition: string.c:243
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56
#define hash_table_undefined
Value of an undefined hash_table.
Definition: newgen_hash.h:49
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
hash_table set_ordering_to_statement(statement s)
To be used instead of initialize_ordering_to_statement() to make sure that the hash table ots is in s...
Definition: ordering.c:172
statement ordering_to_statement(int o)
Get the statement associated to a given ordering.
Definition: ordering.c:111
void reset_ordering_to_statement(void)
Reset the mapping from ordering to statement.
Definition: ordering.c:185
static char * module
Definition: pips.c:74
#define print_effect(e)
Definition: print.c:336
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
static const char * prefix
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define statement_block_p(stat)
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define is_instruction_block
soft block->sequence transition
#define entity_variable_p(e)
An entity_variable_p(e) may hide a typedef and hence a functional type.
#define instruction_block(i)
bool dynamic_area_p(entity aire)
Definition: area.c:68
bool static_area_p(entity aire)
Definition: area.c:77
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
entity FindEntity(const char *package, const char *name)
Retrieve an entity from its package/module name and its local name.
Definition: entity.c:1503
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
bool entity_in_list_p(entity ent, list ent_l)
look for ent in ent_l
Definition: entity.c:2221
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
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
string storage_to_string(storage s)
Definition: entity.c:2030
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
void print_entities(list l)
Definition: entity.c:167
bool top_level_entity_p(entity e)
Check if the scope of entity e is global.
Definition: entity.c:1130
bool parameter_passing_by_value_p(entity f)
Definition: entity.c:2116
type ultimate_type(type)
Definition: type.c:3466
list load_statement_enclosing_loops(statement)
void AddLocalEntityToDeclarations(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:233
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
int add_C_variable_to_area(entity, entity)
Definition: variable.c:1381
void store_statement_enclosing_loops(statement, list)
statement_mapping get_enclosing_loops_map(void)
int add_variable_to_area(entity, entity)
Definition: variable.c:1376
void set_enclosing_loops_map(statement_mapping)
#define type_functional_p(x)
Definition: ri.h:2950
#define loop_body(x)
Definition: ri.h:1644
@ is_basic_overloaded
Definition: ri.h:574
#define value_code_p(x)
Definition: ri.h:3065
#define storage_formal_p(x)
Definition: ri.h:2522
#define instruction_loop_p(x)
Definition: ri.h:1518
#define call_function(x)
Definition: ri.h:709
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define instruction_loop(x)
Definition: ri.h:1520
#define statement_ordering(x)
Definition: ri.h:2454
#define test_false(x)
Definition: ri.h:2837
#define basic_tag(x)
Definition: ri.h:613
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define 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 statement_label(x)
Definition: ri.h:2450
@ is_storage_ram
Definition: ri.h:2492
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_expression
Definition: ri.h:1478
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define entity_name(x)
Definition: ri.h:2790
#define test_true(x)
Definition: ri.h:2835
#define statement_extensions(x)
Definition: ri.h:2464
#define value_code(x)
Definition: ri.h:3067
#define instruction_forloop(x)
Definition: ri.h:1538
#define loop_locals(x)
Definition: ri.h:1650
#define instruction_whileloop(x)
Definition: ri.h:1523
#define whileloop_body(x)
Definition: ri.h:3162
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define storage_ram(x)
Definition: ri.h:2521
#define control_statement(x)
Definition: ri.h:941
#define instruction_test(x)
Definition: ri.h:1517
#define entity_type(x)
Definition: ri.h:2792
#define statement_number(x)
Definition: ri.h:2452
#define code_language(x)
Definition: ri.h:792
#define language_tag(x)
Definition: ri.h:1590
#define type_variable_p(x)
Definition: ri.h:2947
#define forloop_body(x)
Definition: ri.h:1372
#define instruction_unstructured(x)
Definition: ri.h:1532
@ is_language_fortran
Definition: ri.h:1566
#define loop_index(x)
Definition: ri.h:1640
#define variable_basic(x)
Definition: ri.h:3120
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
char * strdup()
return(s1)
#define ifdebug(n)
Definition: sg.c:47
#define intptr_t
Definition: stdint.in.h:294
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54
static int depth
la sequence de nids
void module_clean_declarations(entity module, statement module_statement)
declarations.c
Definition: declarations.c:140
bool localize_declaration(const string)
bool privatize_module(const string)
privatize.c
bool privatize_module_even_globals(const string)