PIPS
util.c
Go to the documentation of this file.
1 /*
2 
3  $Id: util.c 23495 2018-10-24 09:19:47Z 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 #include <stdlib.h>
25 #ifndef _GNU_SOURCE
26 /* For strdup: */
27 #define _GNU_SOURCE
28 #endif // _GNU_SOURCE
29 #include <string.h>
30 
31 #ifdef HAVE_CONFIG_H
32  #include "pips_config.h"
33 #endif
34 
35 #include "local.h"
36 #include "prettyprint.h"
37 #include "rice.h"
38 
39 
40 /* Vertex_to_statement looks for the statement that is pointed to by
41 vertex v. This information is kept in a static hash_table named
42 OrderingToStatement. See ri-util/ordering.c for more information.
43 */
44 
46 {
49 }
50 
52 {
54  return dg_vertex_label_statement(dvl);
55 }
56 
57 /* compare two vertices based on their ordering */
58 int compare_vertex(const void *v0, const void *v1)
59 {
60  const vertex V0 = *(const vertex *)v0,
61  V1 = *(const vertex *)v1;
62  if (V0==V1) return 0;
63  return vertex_ordering(V0) > vertex_ordering(V1);
64 }
65 
66 
67 /* Define a mapping from the statement ordering to the dependence
68  graph vertices: */
71 {
72  hash_table ordering_to_dg_mapping = hash_table_make(hash_int, 0);
73 
74  FOREACH(VERTEX, a_vertex, graph_vertices(dependance_graph))
75  {
76  pips_debug(7, "\tSuccessor list: %p for statement ordering %lld\n",
77  vertex_successors(a_vertex),
78  (long long int) dg_vertex_label_statement(vertex_vertex_label(a_vertex)));
79 
80  hash_put(ordering_to_dg_mapping,
82  (char *) a_vertex);
83  }
84 
85  return ordering_to_dg_mapping;
86 }
87 
88 ␌
89 static string dependence_graph_banner[8] = {
90  "\n *********************** Use-Def Chains *********************\n",
91  "\n **************** Effective Dependence Graph ****************\n",
92  "\n ********* Dependence Graph (ill. option combination) *******\n",
93  "\n ********* Dependence Graph (ill. option combination) *******\n",
94  "\n ******** Whole Dependence Graph with Dependence Cones ******\n",
95  "\n ********* Dependence Graph (ill. option combination) *******\n",
96  "\n ********* Dependence Graph (ill. option combination) *******\n",
97  "\n **** Loop Carried Dependence Graph with Dependence Cones ***\n"
98  };
99 
100 
101 /**
102  * @brief This is a callback for qsort function, it compares two vertex
103  * @return 0 if these are equals, -1 if first is lower, 1 if second is lower
104  */
105 int vertex_sort_callback( const vertex *v1, const vertex *v2 ) {
107  statement s2 = vertex_to_statement( *v2 );
108  return statement_number(s1) > statement_number(s2);
109 }
110 
111 
112 /**
113  * @brief This is a callback for qsort function, it compares two successor
114  * @return 0 if these are equals, -1 if first is lower, 1 if second is lower
115  */
116 int successor_sort_callback( const successor *succ1, const successor *succ2 ) {
117  vertex v1 = successor_vertex(*succ1);
118  vertex v2 = successor_vertex(*succ2);
119  return vertex_sort_callback( &v1, &v2 );
120 }
121 
122 /**
123  * @brief This is a callback for qsort function, it compares two conflicts
124  * @return 0 if conflicts are equals, -1 if first is lower, 1 if second is lower
125  */
127  int r_value = 0;
128  effect e1_sink = conflict_sink((*c1));
129  effect e2_sink = conflict_sink((*c2));
130  action a1_sink = effect_action(e1_sink);
131  action a2_sink = effect_action(e2_sink);
132  effect e1_source = conflict_source((*c1));
133  effect e2_source = conflict_source((*c2));
134  action a1_source = effect_action(e1_source);
135  action a2_source = effect_action(e2_source);
136 
137 
138 
139  string s1 = strdup(concatenate(full_action_to_short_string(a1_source),
141  NULL));
142  string s2 = strdup(concatenate(full_action_to_short_string(a2_source),
144  NULL));
145 
146  // Compare Action in lexical order
147  r_value = strcmp( s1, s2 );
148  free( s1 );
149  free( s2 );
150 
151  if ( r_value == 0 ) {
152  // Compare string representing source reference
153  reference r1_source = effect_any_reference(e1_source);
154  string s1 = words_to_string( effect_words_reference( r1_source ) );
155  reference r2_source = effect_any_reference(e2_source);
156  string s2 = words_to_string( effect_words_reference( r2_source ) );
157  r_value = strcmp( s1, s2 );
158  free( s1 );
159  free( s2 );
160  }
161  if ( r_value == 0 ) {
162  // Compare string representing sink reference
163  reference r1_sink = effect_any_reference(e1_sink);
164  string s1 = words_to_string( effect_words_reference( r1_sink ) );
165  reference r2_sink = effect_any_reference(e2_sink);
166  string s2 = words_to_string( effect_words_reference( r2_sink ) );
167  r_value = strcmp( s1, s2 );
168  free( s1 );
169  free( s2 );
170  }
171 
172  return r_value;
173 }
174 
175 
176 /* Print all edges and arcs */
179  graph mod_graph )
180 {
181  cons *pv1, *ps, *pc;
182  Ptsg gs;
183  int banner_number = 0;
184  bool sru_format_p =
185  get_bool_property( "PRINT_DEPENDENCE_GRAPH_USING_SRU_FORMAT" );
187  int dl = -1;
188  debug_on("RICEDG_DEBUG_LEVEL");
189 
190  ifdebug(8) {
191  /* There is no guarantee that the ordering_to_statement()
192  * hash table is the proper one */
194  }
195 
196  if ( sru_format_p && !statement_undefined_p(mod_stat) ) {
197  /* compute line numbers for statements */
200  } else {
201  banner_number
202  = get_bool_property( "PRINT_DEPENDENCE_GRAPH_WITHOUT_PRIVATIZED_DEPS" )
203  + 2 * get_bool_property( "PRINT_DEPENDENCE_GRAPH_WITHOUT_NOLOOPCARRIED_DEPS" )
204  + 4 * get_bool_property( "PRINT_DEPENDENCE_GRAPH_WITH_DEPENDENCE_CONES" );
205  fprintf( fd, "%s\n", dependence_graph_banner[banner_number] );
206  }
207 
209  for ( pv1 = graph_vertices(mod_graph); !ENDP(pv1); pv1 = CDR(pv1) ) {
210  vertex v1 = VERTEX(CAR(pv1));
213  for ( ps = vertex_successors(v1); !ENDP(ps); ps = CDR(ps) ) {
214  successor su = SUCCESSOR(CAR(ps));
215  vertex v2 = successor_vertex(su);
216  statement s2 = vertex_to_statement( v2 );
218 
219  /* If we have zero printable conflicts, move on.
220  *
221  * If we have more than one conflict, let's sort them !
222  *
223  * FI: the number of conflicts should take into account the
224  * filtering due to PRETTYPRINT_MEMORY_EFFECTS_ONLY
225  */
226  list cl = dg_arc_label_conflicts(dal);
227  int nb_conflicts = gen_length(cl);
228  if(get_bool_property("PRETTYPRINT_MEMORY_EFFECTS_ONLY")) {
229  FOREACH(CONFLICT, c, cl) {
230  effect efsrc = conflict_source(c);
231  if(!store_effect_p(efsrc))
232  nb_conflicts--;
233  }
234  }
235 
236  if(nb_conflicts==0)
237  continue;
238 
239  if ( !sru_format_p || statement_undefined_p(mod_stat) ) {
240  /* Modification at revision 12484 because statement
241  numbers were not initialized by C parser, with no
242  validation of ricedg available at that time*/
243  /* factorize line numbers */
244  //fprintf(fd, "\t%s -->",
245  // external_statement_identification(s1)
246  // Revision 10893: %02d and statement_number (Pham Dat)
247  fprintf( fd, "\t%02td -->", statement_number(s1) );
248  //fprintf(fd, " %s with conflicts\n",
249  // external_statement_identification(s2)
250  fprintf( fd, " %02td with conflicts\n", statement_number(s2) );
251  }
252 
253  if ( nb_conflicts > 1 ) {
254  /*
255  * Convert the list to an array for sorting
256  * 20 is the initial size, should be enough for most cases
257  *
258  * FI: should generate a bug anytime when calls are
259  * involved. At least use dependent types... or pass gen_length()
260  */
261  gen_array_t conflicts_array = gen_array_make( 20 );
262  list_to_array( dg_arc_label_conflicts(dal), conflicts_array );
263  qsort( gen_array_pointer( conflicts_array ),
264  gen_array_nitems( conflicts_array ),
265  sizeof(void *),
267  list conflicts_list = NIL;
268  GEN_ARRAY_FOREACH(conflict, s, conflicts_array)
269  conflicts_list = CONS(conflict, s, conflicts_list);
270  gen_array_free(conflicts_array);
271  dg_arc_label_conflicts(dal)=conflicts_list;
272  }
273 
274  /*
275  * Loop over conflict and print them
276  */
277  for ( pc = dg_arc_label_conflicts(dal); !ENDP(pc); pc = CDR(pc) ) {
278  conflict c = CONFLICT(CAR(pc));
279  effect efsrc = conflict_source(c);
280 
281  /* FI: I should use another property, specific to the use-def
282  chains, but this is quite close */
283  if(store_effect_p(efsrc)
284  || !get_bool_property("PRETTYPRINT_MEMORY_EFFECTS_ONLY")) {
285 
286  /* if (!entity_scalar_p(reference_variable
287  (effect_any_reference(conflict_source(c))))) {
288  */
289  if ( sru_format_p && !statement_undefined_p(mod_stat) ) {
290  int l1 = dl + apply_persistant_statement_to_int( s_to_l, s1 );
291  int l2 = dl + apply_persistant_statement_to_int( s_to_l, s2 );
292 
293  fprintf( fd, "%d %d ", l1, l2 );
294  /*
295  fprintf(fd, "%d %d ",
296  statement_number(s1), statement_number(s2));
297  */
298  fprintf( fd,
299  "%s %s ",
302  fprintf( fd, "<" );
303  print_words( fd,
306  fprintf( fd, "> - <" );
307  print_words( fd,
310  fprintf( fd, ">" );
311 
312  /* Additional information for EDF prettyprint.
313  Instruction calls are given with statement numbers
314  */
315  if ( get_bool_property( "PRETTYPRINT_WITH_COMMON_NAMES" ) ) {
317  fprintf( fd,
318  " %td-%s",
323  else
324  fprintf( fd, " %td", statement_number(s1) );
326  fprintf( fd,
327  " %td-%s",
328  statement_number(s2),
332  else
333  fprintf( fd, " %td", statement_number(s2) );
334  }
335 
336  } else {
337  fprintf( fd, "\t\tfrom " );
339 
340  fprintf( fd, " to " );
342  }
343 
344  if ( conflict_cone(c) != cone_undefined ) {
345  if ( sru_format_p && !statement_undefined_p(mod_stat) ) {
346  fprintf( fd, " levels(" );
347  MAPL(pl, {
348  fprintf(fd, pl==cone_levels(conflict_cone(c))? "%td" : ",%td",
349  INT(CAR(pl)));
350  }, cone_levels(conflict_cone(c)));
351  fprintf( fd, ") " );
352  } else {
353  fprintf( fd, " at levels " );
354  MAPL(pl, {
355  fprintf(fd, " %td", INT(CAR(pl)));
356  }, cone_levels(conflict_cone(c)));
357  fprintf( fd, "\n" );
358  }
359 
360  if( get_bool_property( "PRINT_DEPENDENCE_GRAPH_WITH_DEPENDENCE_CONES" ) ) {
362  if( !SG_UNDEFINED_P( gs ) ) {
363  if( sru_format_p && !statement_undefined_p(mod_stat) ) {
364  if( sg_nbre_sommets( gs ) == 1 && sg_nbre_rayons( gs ) == 0
365  && sg_nbre_droites( gs ) == 0 ) {
366  /* uniform dependence */
367  fprintf( fd, "uniform" );
368  fprint_lsom_as_dense( fd, sg_sommets( gs ), gs->base );
369  } else {
370  sg_fprint_as_ddv( fd, gs );
371  }
372  } else {
373  /* sg_fprint(fd,gs,entity_local_name); */
374  /* FI: almost print_dependence_cone:-( */
375  sg_fprint_as_dense( fd, gs, gs->base );
376  ifdebug(2) {
377  Psysteme sc1 = sc_new( );
378  sc1 = sg_to_sc_chernikova( gs );
379  (void) fprintf( fd,
380  "syst. lin. correspondant au syst. gen.:\n" );
382  }
383  }
384  }
385  }
386  } else {
387  if ( sru_format_p && !statement_undefined_p(mod_stat) )
388  fprintf( fd, " levels()" );
389  }
390  fprintf( fd, "\n" );
391  }
392  }
393  }
394  }
395 
396  if ( sru_format_p && !statement_undefined_p(mod_stat) ) {
398  } else {
399  fprintf( fd,
400  "\n****************** End of Dependence Graph ******************\n" );
401  }
402 
403  debug_off();
404 }
405 
406 
407 
408 /****************************************************************
409  * FOLLOWING FUNCTIONS ARE INTENDED TO PRODUCE DEPENDENCE GRAPH
410  * IN GRAPHIZ DOT FORMAT
411  */
412 
413 /* Context structure used by gen recurse */
416  bool ordered;
418  FILE *fd;
420 };
422 
423 /** \def dot_nodes_recurse( ctx, s )
424  Recurse on statement s with context ctx
425  Intended to be called while already on a gen_recurse recursion
426  */
427 #define dot_nodes_recurse( ctx, s ) { \
428  ctx->current = s; \
429  gen_context_recurse( s, \
430  ctx, \
431  statement_domain, \
432  prettyprint_dot_nodes, \
433  gen_null2 ); \
434 }
435 
436 /** \def dot_print_label_string( fd, str )
437  print the string str in file descriptor fd, removing all \n
438  */
439 #define dot_print_label_string( fd, str ) \
440 while ( *str ) { \
441  char c = *str++; \
442  if ( c == '"' ) { /* some char must be escaped */ \
443  (void) putc( '\\', fd); \
444  } \
445  if ( c != '\n' ) { \
446  (void) putc( c, fd); \
447  } \
448 }
449 
450 /** \fn static void prettyprint_dot_label( FILE *fd, statement s, bool print_statement )
451  * \brief Print the label for a statement. It will only output the first line
452  * after having removed comments.
453  * \param fd is the file descriptor
454  * \param s is the statement
455  * \param print_statement, if set to false then only print the ordering
456  */
457 static void prettyprint_dot_label( FILE *fd, statement s, bool print_statement ) {
458 
459  if( ! print_statement ) {
460  // Print only ordering
461  long int o = statement_ordering(s);
462  fprintf( fd, "(%ld,%ld)", ORDERING_NUMBER(o), ORDERING_STATEMENT(o));
463  } else {
464  // Print the code
465 
466  // saving comments
467  string i_comments = statement_comments(s);
468 
469  // remove thems
470  statement_comments(s) = string_undefined;
471 
472  // Get the text without comments
473  list sentences =
474  text_sentences(Text_Statement_Enclosed(entity_undefined,0,s,false,true ));
475 
476  // Restoring comments
477  statement_comments(s) = i_comments;
478 
479  // Print the first sentence
480  if(sentences) {
481  sentence sent = SENTENCE(CAR( sentences ));
482  if(sentence_formatted_p(sent)) {
483  string str = sentence_formatted(sent);
484  dot_print_label_string( fd, str );
485  } else {
486  unformatted u = sentence_unformatted(sent);
487  cons *lw = unformatted_words(u);
488  while(lw) {
489  string str = STRING(CAR(lw));
490  dot_print_label_string( fd, str )
491  lw = CDR(lw);
492 
493  }
494  }
495  }
496  }
497 }
498 
499 /** \fn static bool prettyprint_dot_nodes( statement s, dot_ctx ctx )
500  * \brief Print nodes for statements, the recursion is quite complicated.
501  * for instance when we see a loop, we print the header, and we call a
502  * self-gen_recursion on the body to create separate node for each statement
503  * inside the loop.
504  * Called by gen_recurse_context
505  * \param s is the current statement
506  * \param ctx is the gen_recurse context
507  * \return true for blocks and simple statement, false for loop, test, ...
508  */
509 static bool prettyprint_dot_nodes( statement s, dot_ctx ctx ) {
510  bool gen_recurse = true;
511 
512  // We ignore the current statement (infinite recursion) and blocks
513  if(ctx->current != s && ! statement_block_p( s ) ) {
514  int ordering = statement_ordering(s);
515 
516  if ( ctx->ordered ) {
517  // When we have produced a previous statement,
518  // we chain it with current one with a very high weight
519  if ( ctx->previous_ordering > 0 ) {
520  fprintf( ctx->fd,
521  " \"%d\" -> \"%d\";\n",
522  ctx->previous_ordering,
523  ordering ); // We really want ordering to be respected :-)
524  }
525  ctx->previous_ordering = ordering;
526  }
527 
528  // Create the node
529  fprintf( ctx->fd, " %d [label=\"", ordering);
530 
531  // Specials cases
533  switch ( instruction_tag(i) ) {
534  case is_instruction_test:
535  // It's a test, we print the test itself first
536  prettyprint_dot_label( ctx->fd, s, ctx->print_statement );
537  fprintf( ctx->fd, "\"];\n" );
538  // FIXME "else" won't appear in output...
539  // but I've no "simple" solution for the moment :-(
540 
541  // Recurse on test bodies (true & false)
542  dot_nodes_recurse( ctx, s );
543  gen_recurse = false; // No more further recursion
544  break;
546  break;
547  case is_instruction_loop:
550  // We have a loop, first print the header
551  prettyprint_dot_label( ctx->fd, s, ctx->print_statement );
552  fprintf( ctx->fd, "\"];\n" );
553  // Recurse on loop body now
554  dot_nodes_recurse( ctx, s )
555  ;
556  gen_recurse = false; // No more further recursion
557  break;
558  case is_instruction_goto:
559  case is_instruction_unstructured:// FIXME ???
560  case is_instruction_call:
562  default:
563  // Standard output, print the statement
564  prettyprint_dot_label( ctx->fd, s, ctx->print_statement );
565  fprintf( ctx->fd, "\"];\n\n" );
566  break;
567  }
568  }
569  return gen_recurse;
570 }
571 
572 
573 
574 /** \fn void prettyprint_dot_dependence_graph( FILE * fd,
575  * statement mod_stat,
576  * graph mod_graph )
577  * \brief Output dependence graph in a file in graphviz dot format
578  * \param fd is the file descriptor where to output
579  * \param mod_stat is the module statement (not necessary module, it can be
580  * a block statement for instance
581  * \param graph is the dependence graph to print
582  */
585  graph mod_graph ) {
586  debug_on( "RICEDG_DEBUG_LEVEL" );
587 
588  ifdebug(8) {
589  /* There is no guarantee that the ordering_to_statement()
590  * hash table is the proper one */
592  }
593  // Begin graph
594  fprintf( fd, "digraph {\n" );
595 
596 
597  bool centered = get_bool_property( "PRINT_DOTDG_CENTERED" );
598  const char* title = get_string_property( "PRINT_DOTDG_TITLE" );
599  const char* title_position = get_string_property( "PRINT_DOTDG_TITLE_POSITION" );
600  const char* background = get_string_property( "PRINT_DOTDG_BACKGROUND" );
601  const char* nodeshape= get_string_property( "PRINT_DOTDG_NODE_SHAPE" );
602  const char* nodeshapecolor = get_string_property( "PRINT_DOTDG_NODE_SHAPE_COLOR" );
603  const char* nodefillcolor = get_string_property( "PRINT_DOTDG_NODE_FILL_COLOR" );
604  const char* nodefontcolor = get_string_property( "PRINT_DOTDG_NODE_FONT_COLOR" );
605  const char* nodefontsize = get_string_property( "PRINT_DOTDG_NODE_FONT_SIZE" );
606  const char* nodefontface = get_string_property( "PRINT_DOTDG_NODE_FONT_FACE" );
607 
608 
609  /* graph style */
610  fprintf( fd,
611  "\n"
612  " /* graph style */\n");
613  // Print title if not empty
614  if( !same_string_p( title, "" ) ) {
615  fprintf( fd, " label=\"%s\";\n", title);
616  }
617  // Print title location if not empty
618  if( !same_string_p( title_position, "" ) ) {
619  fprintf( fd, " labelloc=\"%s\";\n", title_position);
620  }
621  // Print background color if not empty
622  if( !same_string_p( background, "" ) ) {
623  fprintf( fd, " bgcolor=\"%s\";\n", background);
624  }
625  if( centered ) {
626  fprintf( fd, " center=\"true\";\n");
627  }
628  fprintf( fd, "\n\n");
629 
630 
631 
632  /* Nodes style */
633  fprintf( fd,
634  "\n"
635  " /* Nodes style */\n"
636  " node [shape=\"%s\",color=\"%s\",fillcolor=\"%s\","
637  "fontcolor=\"%s\",fontsize=\"%s\",fontname=\"%s\"];\n\n",
638  nodeshape,
639  nodeshapecolor,
640  nodefillcolor,
641  nodefontcolor,
642  nodefontsize,
643  nodefontface );
644 
645 
646 
647 
648  // Should we print the statement or only its ordering ?
649  bool print_statement = get_bool_property( "PRINT_DOTDG_STATEMENT" );
650  // Should node be ordered top down according to the statement ordering ?
651  bool ordered = get_bool_property( "PRINT_DOTDG_TOP_DOWN_ORDERED" );
652 
653  if( ordered || print_statement ) {
654  fprintf( fd,
655  "\n {\n /* Print nodes for statements %s order them */\n\n",
656  ordered ? "and" : "but don't" );
657 
658  if ( ordered ) {
659  fprintf( fd,
660  " /* ordering edges must be invisible, so set background color */\n"
661  " edge [weight=100,color=%s];\n\n",
662  background );
663  }
664 
665  // Generate nodes
666  struct prettyprint_dot_context ctx;
667  ctx.fd = fd;
668  ctx.current = NULL;
669  ctx.ordered = ordered;
671  ctx.previous_ordering = 0;
672 
675  fprintf( fd, " }\n\n" );
676  }
677 
678 
679  fprintf( fd, " /* Print arcs between statements */\n\n" );
680  fprintf( fd, " /* Dependence arcs won't constrain node positions */\nedge [constraint=false];\n\n" );
681 
682 
683 
684  const char* flowdep_color = get_string_property( "PRINT_DOTDG_FLOW_DEP_COLOR" );
685  const char* flowdep_style = get_string_property( "PRINT_DOTDG_FLOW_DEP_STYLE" );
686  const char* antidep_color = get_string_property( "PRINT_DOTDG_ANTI_DEP_COLOR" );
687  const char* antidep_style = get_string_property( "PRINT_DOTDG_ANTI_DEP_STYLE" );
688  const char* outputdep_color = get_string_property( "PRINT_DOTDG_OUTPUT_DEP_COLOR" );
689  const char* outputdep_style = get_string_property( "PRINT_DOTDG_OUTPUT_DEP_STYLE" );
690  const char* inputdep_color = get_string_property( "PRINT_DOTDG_INPUT_DEP_COLOR" );
691  const char* inputdep_style = get_string_property( "PRINT_DOTDG_INPUT_DEP_STYLE" );
692 
693  bool mask_loop_carried = get_bool_property("PRINT_DEPENDENCE_GRAPH_WITHOUT_NOLOOPCARRIED_DEPS");
694  bool mask_loop_privatized = get_bool_property("PRINT_DEPENDENCE_GRAPH_WITHOUT_PRIVATIZED_DEPS");
696 
697  // Loop over the graph and print all dependences
698  FOREACH( vertex, v1 , graph_vertices( mod_graph ) ) {
702  {
703  vertex v2 = successor_vertex( su );
704  statement s2 = vertex_to_statement( v2 );
707  int nbrcomloops = FindMaximumCommonLevel(loops1, loops2);
709  {
710  action source_act = effect_action( conflict_source( c ) );
711  action sink_act = effect_action( conflict_sink( c ) );
712  reference sink_ref = effect_any_reference( conflict_sink( c ) );
713  reference source_ref = effect_any_reference( conflict_source( c ) );
714  const char* color = inputdep_color;
715  const char* style = inputdep_style;
716 
717  /*
718  * Here we check if this arc is only loop carried or not and we might
719  * skip it if required by property
720  */
721  bool keep_this_conflict = true;
722  if(mask_loop_carried && conflict_cone(c) != cone_undefined) {
723  list lls = cone_levels(conflict_cone(c));
724  keep_this_conflict = false;
725  FOREACH(int, level, lls) {
726  if(level > nbrcomloops ) {
727  keep_this_conflict = true;
728  break;
729  }
730  }
731  }
732  bool keep_this_conflict_privatized = true;
733  if(mask_loop_privatized && conflict_cone(c) != cone_undefined) {
734  list lls = cone_levels(conflict_cone(c));
735  keep_this_conflict_privatized = true;
736  FOREACH(int, level, lls) {
737  if(level > nbrcomloops || ignore_this_conflict(v1,v2,c,level)) {
738  keep_this_conflict_privatized=false;
739  //break;
740  }
741  }
742  }
743 
744  keep_this_conflict = keep_this_conflict && keep_this_conflict_privatized;
745  //verify also for level = 0
746  if(mask_loop_privatized && ignore_this_conflict(v1,v2,c,0))
747  keep_this_conflict=false;
748 
749  if(!keep_this_conflict) {
750  continue;
751  }
752 
753 
754  // Ok let's display it now.
755 
756  if( action_read_p( source_act ) && action_write_p( sink_act ) ) {
757  color = antidep_color;
758  style = antidep_style;
759  } else if( action_write_p( source_act ) && action_write_p( sink_act ) ) {
760  color = outputdep_color;
761  style = outputdep_style;
762  } else if( action_write_p( source_act ) && action_read_p( sink_act ) ) {
763  color = flowdep_color;
764  style = flowdep_style;
765  }
766  fprintf( fd,
767  "%d -> %d [color=%s,style=%s,label=\"",
768  (int) statement_ordering(s1),
769  (int) statement_ordering(s2),
770  color,
771  style );
772  fprintf( fd,
773  "%s <",
774  full_action_to_short_string( source_act ));
775  print_words( fd,
776  effect_words_reference( source_ref ) );
777  fprintf( fd, ">\\n" );
778  fprintf( fd,
779  "%s <",
780  full_action_to_short_string( sink_act ));
781  print_words( fd,
782  effect_words_reference( sink_ref ) );
783  fprintf( fd, ">\\n" );
784 
785 
786  // Print the levels and the cone
787  if ( conflict_cone( c ) != cone_undefined ) {
788  fprintf( fd, " levels(" );
789  MAPL(pl, {
790  fprintf(fd, pl==cone_levels(conflict_cone(c))? "%td" : ",%td",
791  INT(CAR(pl)));
792  }, cone_levels(conflict_cone(c)));
793  fprintf( fd, ") " );
794 
795  if ( get_bool_property( "PRINT_DEPENDENCE_GRAPH_WITH_DEPENDENCE_CONES" ) ) {
797  if ( !SG_UNDEFINED_P( gs ) ) {
798  if ( sg_nbre_sommets( gs ) == 1 && sg_nbre_rayons( gs ) == 0
799  && sg_nbre_droites( gs ) == 0 ) {
800  /* uniform dependence */
801  fprintf( fd, "uniform" );
802  fprint_lsom_as_dense( fd, sg_sommets( gs ), gs->base );
803  } else {
804  sg_fprint_as_ddv( fd, gs );
805  }
806  }
807  }
808  } else {
809  fprintf( fd, " levels()" );
810  }
811  fprintf( fd, "\"];\n" );
812  }
813  }
814  }
815 
816  fprintf( fd, "\n}\n" );
817 
819 
820  debug_off( );
821 }
822 
823 /*
824  * END OF OUTPUT IN GRAPHIZ DOT FORMAT
825  ****************************************************************/
826 
827 
828 
829 /* Do not print vertices and arcs ignored by the parallelization algorithms.
830  * At least, hopefully...
831  */
832 void
835  graph mod_graph)
836 {
837  cons *pv1, *ps, *pc;
838  Ptsg gs;
839  int banner_number = 0;
840 
841  banner_number =
842  get_bool_property("PRINT_DEPENDENCE_GRAPH_WITHOUT_PRIVATIZED_DEPS") +
844  ("PRINT_DEPENDENCE_GRAPH_WITHOUT_NOLOOPCARRIED_DEPS") +
846  ("PRINT_DEPENDENCE_GRAPH_WITH_DEPENDENCE_CONES");
847 
848  fprintf(fd, "%s\n", dependence_graph_banner[banner_number]);
849 
851 
852  debug_on("RICEDG_DEBUG_LEVEL");
853 
854  for (pv1 = graph_vertices(mod_graph); !ENDP(pv1); pv1 = CDR(pv1)) {
855  vertex v1 = VERTEX(CAR(pv1));
858 
859  for (ps = vertex_successors(v1); !ENDP(ps); ps = CDR(ps)) {
860  successor su = SUCCESSOR(CAR(ps));
861  vertex v2 = successor_vertex(su);
865 
866  /*
867  * If we have more than one conflict, let's sort them !
868  */
869  int nb_conflicts = gen_length(dg_arc_label_conflicts(dal));
870  if ( nb_conflicts > 1 ) {
871  /*
872  * Convert the list to an array for sorting
873  * 20 is the initial size, should be enough for most of the case
874  */
875  gen_array_t conflicts_array = gen_array_make( 20 );
876  list_to_array( dg_arc_label_conflicts(dal), conflicts_array );
877  qsort( gen_array_pointer( conflicts_array ),
878  gen_array_nitems( conflicts_array ),
879  sizeof(void *),
881  list conflicts_list = NIL;
882  GEN_ARRAY_FOREACH(conflict, s, conflicts_array)
883  conflicts_list = CONS(conflict, s, conflicts_list);
884  gen_array_free(conflicts_array);
885  dg_arc_label_conflicts(dal)=conflicts_list;
886  }
887  int nbrcomloops = FindMaximumCommonLevel(loops1, loops2);
888  for (pc = dg_arc_label_conflicts(dal); !ENDP(pc); pc = CDR(pc)) {
889  conflict c = CONFLICT(CAR(pc));
890 
891  if(conflict_cone(c) == cone_undefined) continue;
892  else {
893  cons * lls = cone_levels(conflict_cone(c));
894  cons *llsred =NIL;
895  if (get_bool_property("PRINT_DEPENDENCE_GRAPH_WITHOUT_PRIVATIZED_DEPS")){
896  MAPL(pl,{
897  _int level = INT(CAR(pl));
898  if (level <= nbrcomloops) {
899  if (! ignore_this_conflict(v1,v2,c,level)) {
900  llsred = gen_nconc(llsred, CONS(INT, level, NIL));
901  }
902  }
903  else {
905  ("PRINT_DEPENDENCE_GRAPH_WITHOUT_NOLOOPCARRIED_DEPS")) {
906  continue;
907  }
908  else llsred = gen_nconc(llsred, CONS(INT, level, NIL));
909  }
910  }, lls);
911  }
912  if (llsred == NIL) continue;
913  else {
914  /*if (! entity_scalar_p(reference_variable
915  (effect_any_reference(conflict_source(c))))) { */
916 
917  fprintf(fd, "\t%02td --> %02td with conflicts\n",
919 
920  fprintf(fd, "\t\tfrom ");
922 
923  fprintf(fd, " to ");
925 
926  fprintf(fd, " at levels ");
927  MAPL(pl, {
928  fprintf(fd, " %td", INT(CAR(pl)));
929  }, llsred);
930 
931  fprintf(fd, "\n");
933  ("PRINT_DEPENDENCE_GRAPH_WITH_DEPENDENCE_CONES")) {
935  if (!SG_UNDEFINED_P(gs)) {
936  /* sg_fprint(fd,gs,entity_local_name); */
937  sg_fprint_as_dense(fd, gs, gs->base);
938  ifdebug(2) {
939  Psysteme sc1 = sc_new();
940  sc1 = sg_to_sc_chernikova(gs);
941  (void) fprintf(fd,"syst. lin. correspondant au syst. gen.:\n");
943  }
944  }
945  fprintf(fd, "\n");
946  }
947  }
948  }
949  }
950  }
951  }
953  debug_off();
954  fprintf(fd, "\n****************** End of Dependence Graph "
955  "******************\n");
956 }
957 
958 void
960 FILE *fd;
961 Pvecteur v;
962 Pbase b;
963 {
964  fprintf(fd,"(");
965  for(; b!=NULL; b=b->succ) {
966  fprint_string_Value(fd, " ",vect_coeff(b->var,v));
967  if(b->succ !=NULL)
968  fprintf(fd,",");
969  }
970  fprintf(fd," )");
971 }
972 
973 void
975 FILE *fd;
976 Ptsg dc;
977 Pbase basis;
978 {
979  Psommet v;
980  Pray_dte r;
981  fprintf(fd,"\nDependence cone :\n");
982  if (SG_UNDEFINED_P(dc)) fprintf(fd, "NULL \n");
983  else {
984  fprintf(fd,"basis :");
986  fprintf(fd,"%d vertice(s) :",sg_nbre_sommets(dc));
987  v = sg_sommets(dc);
988  for(; v!=NULL; v= v->succ) {
989  fprint_string_Value(fd, " \n\t denominator = ", v->denominateur);
990  fprintf(fd, "\t");
992  }
993 
994  fprintf(fd,"\n%d ray(s) : ",sg_nbre_rayons(dc));
995 
996  for(r = sg_rayons(dc); r!=NULL; r=r->succ)
998 
999  fprintf(fd,"\n%d line(s) : ",sg_nbre_droites(dc));
1000 
1001  for(r = sg_droites(dc); r!=NULL; r=r->succ)
1003  fprintf(fd,"\n");
1004  }
1005 }
1006 
1007 ␌
1008 
1009 /**
1010  * creates a hash_table containing statements from @a statements as keys and their respective succesors according to @a dg as values
1011  *
1012  * @param statements input statements
1013  * @param dg dependecy graph
1014  *
1015  * @return allocated hash_table with (statement,successors pairs)
1016  */
1017 hash_table
1019 {
1022  {
1024  if( !statement_undefined_p(gen_find_eq(s,statements)))
1025  {
1026  list succ = vertex_successors(v);
1027  hash_put(successors,s,succ);
1028  }
1029  }
1030  return successors;
1031 }
1032 
1033 
1034 /* That's all */
intptr_t apply_persistant_statement_to_int(persistant_statement_to_int f, statement k)
Definition: ri.c:1654
void free_persistant_statement_to_int(persistant_statement_to_int p)
Definition: ri.c:1618
void list_to_array(list l, gen_array_t a)
args.c
Definition: args.c:38
void fprint_string_Value(FILE *, char *, Value)
Definition: io.c:47
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
gen_array_t gen_array_make(size_t size)
declarations...
Definition: array.c:40
void ** gen_array_pointer(const gen_array_t a)
Observers...
Definition: array.c:125
void gen_array_free(gen_array_t a)
Definition: array.c:70
@ INT
Definition: atomic.c:48
static graph dg
dg is the dependency graph ; FIXME : should not be static global ?
Definition: chains.c:124
Psysteme sg_to_sc_chernikova(Ptsg sg)
Definition: chernikova.c:58
static list successors(list l)
#define cone_generating_system(x)
Definition: dg.h:130
#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 cone_levels(x)
Definition: dg.h:128
#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
#define cone_undefined
Definition: dg.h:104
struct _newgen_struct_dg_vertex_label_ * dg_vertex_label
Definition: dg.h:68
#define conflict_cone(x)
Definition: dg.h:169
list words_effect(effect)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
list effect_words_reference(reference)
prettyprint.c
Definition: prettyprint.c:68
string full_action_to_short_string(action)
Definition: effects.c:969
bool store_effect_p(effect)
Definition: effects.c:1062
#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
char * get_string_property(const char *)
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
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void free(void *)
#define successor_vertex(x)
Definition: graph.h:118
#define successor_arc_label(x)
Definition: graph.h:116
#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
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
void clean_enclosing_loops(void)
Definition: loop.c:58
statement_mapping loops_mapping_of_statement(statement stat)
Definition: loop.c:155
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#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
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
#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
void gen_sort_list(list l, gen_cmp_func_t compare)
Sorts a list of gen_chunks in place, to avoid allocations...
Definition: list.c:796
persistant_statement_to_int statement_to_line_number(statement)
Definition: statement.c:2460
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
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
static statement mod_stat
We want to keep track of the current statement inside the recurse.
Definition: impact_check.c:41
void base_fprint(FILE *f, Pbase b, get_variable_name_t variable_name)
void base_fprint(FILE * f, Pbase b, char * (*variable_name)()): impression d'une base sur le fichier ...
Definition: io.c:342
#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 debug_off()
Definition: misc-local.h:160
#define GEN_ARRAY_FOREACH(type, s, array)
Definition: newgen_array.h:50
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
@ hash_int
Definition: newgen_hash.h:32
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26
#define same_string_p(s1, s2)
intptr_t _int
_INT
Definition: newgen_types.h:53
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
void print_ordering_to_statement(void)
Dump the ordering with the corresponding statement address.
Definition: ordering.c:71
statement ordering_to_statement(int o)
Get the statement associated to a given ordering.
Definition: ordering.c:111
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783
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
string safe_entity_name(entity e)
predicates and functions for entities
Definition: entity.c:433
int module_to_declaration_length(entity func)
Number of user declaration lines for a module.
Definition: module.c:352
list load_statement_enclosing_loops(statement)
void reset_enclosing_loops_map(void)
void set_enclosing_loops_map(statement_mapping)
#define call_function(x)
Definition: ri.h:709
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
@ 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_sequence
Definition: ri.h:1469
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define instruction_call_p(x)
Definition: ri.h:1527
#define statement_instruction(x)
Definition: ri.h:2458
#define persistant_statement_to_int_undefined
Definition: ri.h:1915
#define instruction_call(x)
Definition: ri.h:1529
#define statement_undefined_p(x)
Definition: ri.h:2420
#define statement_number(x)
Definition: ri.h:2452
bool ignore_this_conflict(vertex v1, vertex v2, conflict c, int l)
This function checks if conflict c between vertices v1 and v2 should be ignored at level l.
Definition: codegen.c:163
statement vertex_to_statement(vertex v)
Vertex_to_statement looks for the statement that is pointed to by vertex v.
Definition: util.c:45
void prettyprint_dependence_graph_view(FILE *fd, statement mod_stat, graph mod_graph)
Do not print vertices and arcs ignored by the parallelization algorithms.
Definition: util.c:833
#define dot_nodes_recurse(ctx, s)
Recurse on statement s with context ctx Intended to be called while already on a gen_recurse recursio...
Definition: util.c:427
void prettyprint_dependence_graph(FILE *fd, statement mod_stat, graph mod_graph)
Print all edges and arcs.
Definition: util.c:177
static void prettyprint_dot_label(FILE *fd, statement s, bool print_statement)
Print the label for a statement.
Definition: util.c:457
hash_table compute_ordering_to_dg_mapping(graph dependance_graph)
Define a mapping from the statement ordering to the dependence graph vertices:
Definition: util.c:70
hash_table statements_to_successors(list statements, graph dg)
creates a hash_table containing statements from statements as keys and their respective succesors acc...
Definition: util.c:1018
struct prettyprint_dot_context * dot_ctx
Definition: util.c:421
static bool prettyprint_dot_nodes(statement s, dot_ctx ctx)
Print nodes for statements, the recursion is quite complicated.
Definition: util.c:509
void print_vect_in_vertice_val(FILE *fd, Pvecteur v, Pbase b)
Definition: util.c:959
static string dependence_graph_banner[8]
Definition: util.c:89
int vertex_sort_callback(const vertex *v1, const vertex *v2)
This is a callback for qsort function, it compares two vertex.
Definition: util.c:105
int vertex_ordering(vertex v)
Definition: util.c:51
void prettyprint_dot_dependence_graph(FILE *fd, statement mod_stat, graph mod_graph)
Output dependence graph in a file in graphviz dot format.
Definition: util.c:583
int compare_vertex(const void *v0, const void *v1)
compare two vertices based on their ordering
Definition: util.c:58
int conflicts_sort_callback(conflict *c1, conflict *c2)
This is a callback for qsort function, it compares two conflicts.
Definition: util.c:126
void print_dependence_cone(FILE *fd, Ptsg dc, Pbase basis)
Definition: util.c:974
int successor_sort_callback(const successor *succ1, const successor *succ2)
This is a callback for qsort function, it compares two successor.
Definition: util.c:116
int FindMaximumCommonLevel(cons *, cons *)
Definition: testdep_util.c:307
Psysteme sc_new(void)
Psysteme sc_new(): alloue un systeme vide, initialise tous les champs avec des valeurs nulles,...
Definition: sc_alloc.c:55
#define level
void sc_fprint(FILE *fp, Psysteme ps, get_variable_name_t nom_var)
void sc_fprint(FILE * f, Psysteme ps, char * (*nom_var)()): cette fonction imprime dans le fichier po...
Definition: sc_io.c:220
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
s1
Definition: set.c:247
#define sg_sommets(sg)
vieilles definitions des fonctions d'impression void sg_fprint(); #define print_sg(sg) sg_fprint(stdo...
Definition: sg-local.h:85
#define sg_rayons(sg)
acces au premier rayon de la liste des rayons d'un systeme generateur defini par un pointeur: sg_rayo...
Definition: sg-local.h:89
struct type_sg * Ptsg
Representation d'un systeme generateur par trois ensembles de sommets de rayons et de droites.
#define sg_nbre_sommets(sg)
nombre de sommets: int sg_nbre_sommets(Ptsg)
Definition: sg-local.h:96
#define SG_UNDEFINED_P(sg)
Definition: sg-local.h:74
#define sg_nbre_droites(sg)
nombre de droites: int sg_nbre_droites(Ptsg)
Definition: sg-local.h:102
#define sg_nbre_rayons(sg)
nombre de rayons: int sg_nbre_rayons(Ptsg)
Definition: sg-local.h:99
#define sg_droites(sg)
acces a la premiere droite de la liste des droites d'un systeme generateur defini par un pointeur: sg...
Definition: sg-local.h:93
#define ifdebug(n)
Definition: sg.c:47
void sg_fprint_as_dense(FILE *f, Ptsg sg, Pbase b)
void sg_fprint_as_dense(FILE * f, Ptsg sg): impression d'un systeme generateur
Definition: sg.c:298
void sg_fprint_as_ddv(FILE *fd, Ptsg sg)
Definition: sg.c:341
void fprint_lsom_as_dense(FILE *f, Psommet ls, Pbase b)
void fprint_lsom_as_dense(FILE * f, Psommet s): impression d'une liste de sommets
Definition: sommet.c:191
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
Variable var
Definition: vecteur-local.h:90
struct Svecteur * succ
Definition: vecteur-local.h:92
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Context structure used by gen recurse.
Definition: util.c:414
statement current
Definition: util.c:419
struct rdte * succ
Definition: ray_dte-local.h:46
struct Svecteur * vecteur
Definition: ray_dte-local.h:45
structure de donnees Sommet
Definition: sommet-local.h:64
struct typ_som * succ
Definition: sommet-local.h:68
Pvecteur vecteur
Definition: sommet-local.h:66
Value denominateur
Definition: sommet-local.h:67
Representation d'un systeme generateur par trois ensembles de sommets de rayons et de droites.
Definition: sg-local.h:66
Pbase base
Definition: sg-local.h:70
string words_to_string(cons *lw)
Definition: print.c:211
void print_words(FILE *fd, cons *lw)
Definition: print.c:263
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62
Value vect_coeff(Variable var, Pvecteur vect)
Variable vect_coeff(Variable var, Pvecteur vect): coefficient de coordonnee var du vecteur vect —> So...
Definition: unaires.c:228