PIPS
clean_up_sequences.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include "linear.h"
#include "genC.h"
#include "ri.h"
#include "ri-util.h"
#include "properties.h"
#include "misc.h"
+ Include dependency graph for clean_up_sequences.c:

Go to the source code of this file.

Data Structures

struct  cusq_context
 Clean up sequences context. More...
 

Functions

void initialize_clean_up_sequences_statistics (void)
 
void display_clean_up_sequences_statistics (void)
 
static bool store_reference (reference ref, cusq_context *p_ctxt)
 
static bool store_loops (loop l, cusq_context *p_ctxt)
 
static bool store_declarations_references (statement st, cusq_context *p_ctxt)
 
static void cusq_ctxt_init (statement s, cusq_context *p_ctxt)
 
static void cusq_ctxt_reset (cusq_context *p_ctxt)
 
static void replace_entities_in_cusq_context (cusq_context *p_ctxt, hash_table ht)
 replace entities in the module references and loop indices and loop locals stored in the input cusq_context using the input old/new entities mapping More...
 
bool statement_to_goto_table_flt (instruction i)
 End: clean up sequences context. More...
 
void compute_statement_to_goto_table (statement s)
 Since clean_up_sequences() is called before the controlizer, there may be some GOTO. More...
 
void discard_statement_to_goto_table (void)
 Discard the statement_to_goto_table map: More...
 
void adjust_goto_from_to (statement s1, statement s2)
 Adjust all the GOTOs pointing s1 to s2: More...
 
static void deal_with_pending_comment (statement s, string *the_comments)
 
static bool sequence_proper_declarations_rename_in_place (sequence seq, hash_table renamings)
 change the declarations of declaration statements directly contained in input sequence according to the input old/new entity mapping More...
 
static void clean_up_sequences_rewrite (statement s, cusq_context *p_ctxt)
 
bool clean_up_sequences_internal (statement s)
 An entry point for internal usage, such as from take_out_the_exit_node_if_not_a_continue(): More...
 
bool clean_up_sequences (statement s)
 Recursively clean up the statement sequences by fusing them if possible and by removing useless one. More...
 

Variables

static int clean_up_empty_block_removed
 Clean up the sequences and their contents by fusing them or removing useless continues or empty instructions. More...
 
static int clean_up_fused_sequences
 
static int clean_up_1_statement_sequence
 
hash_table statement_to_goto_table = NULL
 clean_up_sequences.c More...
 

Function Documentation

◆ adjust_goto_from_to()

void adjust_goto_from_to ( statement  s1,
statement  s2 
)

Adjust all the GOTOs pointing s1 to s2:

Parameters
s11
s22

Definition at line 282 of file clean_up_sequences.c.

284 {
285  if (s1 == s2)
286  // Nothing to do:
287  return;
288 
290  {
292  {
293  pips_assert("The GOTO should point to s1.\n",
294  instruction_goto(i) == s1);
295  instruction_goto(i) = s2;
296  pips_debug(6, "Adjusting GOTO from instruction %p -> statement %p to "
297  "statement %p.\n",
298  i, s1, s2);
299  }
300  }
301 }
hash_table statement_to_goto_table
clean_up_sequences.c
#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
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
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
Definition: hash.c:484
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define instruction_goto(x)
Definition: ri.h:1526
s1
Definition: set.c:247
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References FOREACH, hash_defined_p(), hash_get(), instruction_goto, pips_assert, pips_debug, s1, and statement_to_goto_table.

Referenced by clean_up_sequences_rewrite().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ clean_up_sequences()

bool clean_up_sequences ( statement  s)

Recursively clean up the statement sequences by fusing them if possible and by removing useless one.

Remove also empty blocs and useless continues.

Definition at line 704 of file clean_up_sequences.c.

705 {
706 
707  debug_on("CLEAN_UP_SEQUENCES_DEBUG_LEVEL");
709 
710  bool changed = clean_up_sequences_internal(s);
711 
713  debug_off();
714 
715  return changed;
716 }
bool clean_up_sequences_internal(statement s)
An entry point for internal usage, such as from take_out_the_exit_node_if_not_a_continue():
void initialize_clean_up_sequences_statistics(void)
void display_clean_up_sequences_statistics(void)
#define debug_on(env)
Definition: misc-local.h:157
#define debug_off()
Definition: misc-local.h:160

References clean_up_sequences_internal(), debug_off, debug_on, display_clean_up_sequences_statistics(), and initialize_clean_up_sequences_statistics().

Referenced by clear_labels(), control_graph(), delay_communications(), delay_communications_interprocedurally(), delay_load_communications(), delay_store_communications(), do_it(), do_symbolic_tiling(), flatten_code(), freia_compiler(), full_loop_unroll(), if_conv_init_statement(), invariant_code_motion(), new_atomizer(), normalize_microcode(), optimize_expressions(), simd_remove_reductions(), simdizer(), simdizer_init(), statement_split_initializations(), symbolic_tiling(), transform_a_for_loop_into_a_while_loop(), transform_a_for_loop_statement_into_a_while_loop(), and unspaghettify_or_restructure_statement().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ clean_up_sequences_internal()

bool clean_up_sequences_internal ( statement  s)

An entry point for internal usage, such as from take_out_the_exit_node_if_not_a_continue():

Definition at line 676 of file clean_up_sequences.c.

677 {
678  debug_on("CLEAN_UP_SEQUENCES_DEBUG_LEVEL");
679 
681 
682  cusq_context ctxt;
683  cusq_ctxt_init(s, &ctxt);
684 
685  gen_context_recurse(s, &ctxt,
687 
688  cusq_ctxt_reset(&ctxt);
690 
691  ifdebug(1) {
693  }
694  debug_off();
695 
696  return ctxt.changed;
697 }
bool statement_consistent_p(statement p)
Definition: ri.c:2195
static void clean_up_sequences_rewrite(statement s, cusq_context *p_ctxt)
void compute_statement_to_goto_table(statement s)
Since clean_up_sequences() is called before the controlizer, there may be some GOTO.
void discard_statement_to_goto_table(void)
Discard the statement_to_goto_table map:
static void cusq_ctxt_reset(cusq_context *p_ctxt)
static void cusq_ctxt_init(statement s, cusq_context *p_ctxt)
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define ifdebug(n)
Definition: sg.c:47
Clean up sequences context.

References cusq_context::changed, clean_up_sequences_rewrite(), compute_statement_to_goto_table(), cusq_ctxt_init(), cusq_ctxt_reset(), debug_off, debug_on, discard_statement_to_goto_table(), gen_context_recurse, gen_true2(), ifdebug, statement_consistent_p(), and statement_domain.

Referenced by clean_up_sequences(), and take_out_the_exit_node_if_not_a_continue().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ clean_up_sequences_rewrite()

static void clean_up_sequences_rewrite ( statement  s,
cusq_context p_ctxt 
)
static

Delete empty instruction and fuse blocks of instructions :

Remove the list of unused statements with the statements themselves:

|| !ENDP(statement_declarations(s))

We have a pending comment we were not able to attach. Create a continue statement to attach it:

Keep track of declarations within an empty sequence: see C_syntax/block01.c

A sequence of only 1 instruction can be replaced by this instruction, if it has not declarations

Do not forget to adjust the GOTOs pointing on st:

Discard the old statement:

Definition at line 354 of file clean_up_sequences.c.

355 {
357 
358  // nothing to do
359  if (!instruction_sequence_p(i))
360  return;
361 
362  /* Delete empty instruction and fuse blocks of instructions : */
363  list useful_sts, delete_sts;
364  string the_comments = NULL;
365 
366  useful_sts = delete_sts = NIL;
367 
370  && unlabelled_statement_p(s)))
371  {
372  user_log("Statement %s\n"
373  "Number=%d, label=\"%s\", comment=\"%s\"\n",
377  "" : statement_comments(s));
378  pips_internal_error("This block statement should be labelless, numberless"
379  " and commentless.\n");
380  }
381 
382  /*
383  pips_assert("This statement should be labelless, numberless and commentless.",
384  statement_with_empty_comment_p(s)
385  && statement_number(s) == STATEMENT_NUMBER_UNDEFINED
386  && unlabelled_statement_p(s));
387  */
388 
389  pips_debug(3, "A sequence of %zd statements with %zd declarations\n",
392 
393  list l_new_decls = NIL; // newly declared entities if need be.
395 
397  {
399  ifdebug(8)
400  fprintf(stderr, "[ Empty statement or continue ]\n");
401 
403  // Keep the comment to put it on the next useful statement:
404  if (the_comments == NULL)
405  // No comment has been gathered up to now:
406  the_comments = statement_comments(st);
407  else {
408  string nc = statement_comments(st);
409  // FI: apparently, no need to insert a LF between two fused comments.
410  // I suppose that non-empty comments end up with LF
411  string new_comments =
412  strdup(concatenate(the_comments, nc, NULL));
413  free(the_comments);
414  the_comments = new_comments;
415  }
417  }
418  // Unused instructions can be deleted in any order... :-)
419  delete_sts = CONS(STATEMENT, st, delete_sts);
420  pips_debug(3, "Empty block removed...\n");
422  p_ctxt->changed = true;
423  }
424  else
425  {
426  // take care of declarations from the statements directly in the internal sequence
427  list l_internal_proper_decls = statement_to_direct_declarations(st);
428 
429  ifdebug(4){
430  pips_debug(4, "l_internal_proper_decls = \n");
431  print_entities(l_internal_proper_decls);
432  fprintf(stderr, "\n");
433  pips_debug(4, "internal statement declarations");
435  fprintf(stderr, "\n");
436  }
437 
438  if (statement_sequence_p(st)
439  && !empty_statement_p(st)) {
440  // Let fix a special case: an empty sequence with non-empty declarations
441  sequence internal_sequence = statement_sequence(st);
442  list l_stmt_to_be_merged = sequence_statements(internal_sequence);
443  if (ENDP(l_stmt_to_be_merged)) {
444  // If it is not an empty statement, it must contain some declarations.
447  // Now st is an empty statement
448  }
449  }
450 
451  if (statement_sequence_p(st)
452  && !empty_statement_p(st)
453  // The next two tests should be useless
454  // The sequence can be cleaned up even when declarations
455  // and extensions are present
456  // FI: the second part of this test is awful but the
457  // controlizer seems to rely on it... See flatten_code01
458  && ( p_ctxt->merge_sequences_with_declarations ||
459  ENDP(l_internal_proper_decls) || ENDP(statement_declarations(st)))
461 
462  // A sequence with or without declarations in a sequence:
463  // they can be fused:
464  sequence internal_sequence = statement_sequence(st);
465  list l_stmt_to_be_merged = sequence_statements(internal_sequence);
466 
467  if (p_ctxt->merge_sequences_with_declarations &&
468  !ENDP(l_internal_proper_decls))
469  {
471 
472  FOREACH(ENTITY, decl, l_internal_proper_decls)
473  {
474  pips_debug(3, "dealing with declaration: %s\n", entity_name(decl));
475 
476  // check if there is already a variable with the same user name
477  // used in the outermost sequence
478  const char * decl_user_name = entity_user_name(decl);
479  bool parent_decl_with_same_name = false;
480  FOREACH(ENTITY, parent_decl, p_ctxt->l_decl)
481  {
482  // arghh, this is costly, we should at least memoize user_names...
483  if (parent_decl != decl
484  && strcmp(entity_user_name(parent_decl), decl_user_name) == 0)
485  {
486  parent_decl_with_same_name = true;
487  break;
488  }
489  }
490 
491  // find another non-conflicting name and take care of scope
492  bool top_level_entity_with_same_name_p = (FindEntity(TOP_LEVEL_MODULE_NAME, decl_user_name) != entity_undefined);
493  string decl_name = entity_name(decl);
494  string decl_without_module_and_scope = strrchr(decl_name, BLOCK_SEP_CHAR);
495  string new_name = string_undefined;
496  entity new_decl = entity_undefined;
497 
498  pips_debug(6, "decl name without module+scope: %s\n", decl_without_module_and_scope);
499 
500  if (decl_without_module_and_scope == NULL)
501  {
502  // this should generate an error; however, names are sometimes
503  // generated by PIPS phases without scope
504  pips_debug(6, "non consistant variable scope\n");
505  if (top_level_entity_with_same_name_p)
506  new_decl = make_entity_copy_with_new_name_and_suffix(decl, decl_name, true);
507  }
508  else if (decl_without_module_and_scope[-1]=='0' &&
509  decl_without_module_and_scope[-2]== MODULE_SEP_STRING[0])
510  {
511  pips_debug(6, "Entity already at the uppermost scope level\n");
512  if (top_level_entity_with_same_name_p)
513  new_decl = make_entity_copy_with_new_name_and_suffix(decl, decl_name, true);
514  }
515  else
516  {
517  // duplicate the scope, minus the last scope
518  string module_and_new_scope = string_undefined;
519 
520  int i = 2;
521  while (decl_without_module_and_scope[-i] != BLOCK_SEP_CHAR)
522  {
523  if (decl_without_module_and_scope[-i] == MODULE_SEP_STRING[0])
524  pips_internal_error("unexpected MODULE_SEP_STRING, no BLOCK_SEP_CHAR FOUND\n");
525  i++;
526  }
527  if (decl_without_module_and_scope[-i] == BLOCK_SEP_CHAR)
528  module_and_new_scope = strndup(decl_name, decl_without_module_and_scope-decl_name-i+1);
529 
530  pips_debug(6, "module+scope of new decl: %s\n", module_and_new_scope);
531  new_name = strdup(concatenate(module_and_new_scope, decl_user_name, NULL));
532  free(module_and_new_scope);
533 
534  pips_debug(6, "new decl name: %s\n", new_name);
535 
536  if (parent_decl_with_same_name ||
537  top_level_entity_with_same_name_p )
538  new_decl = make_entity_copy_with_new_name_and_suffix(decl, new_name, false);
539  else
540  new_decl = make_entity_copy_with_new_name(decl, new_name, false);
541 
542  // We have to keep the original initial value, because it contains references
543  // which have been gathered in p_ctxt->l_decl and which may have to be renamed.
544  if (!value_undefined_p(entity_initial(decl)))
545  {
546  entity_initial(new_decl) = entity_initial(decl);
548  }
549 
550  pips_debug(3, "new declaration: %s\n", entity_name(new_decl));
551  // add the correspondance for further actual renaming
552  hash_put(renamings, decl, new_decl);
553  l_new_decls = CONS(ENTITY, new_decl, l_new_decls);
554  }
555 
556  if (!entity_undefined_p(new_decl))
557  {
558  // after the merge, the new entity is used in the outermost statement:
559  p_ctxt->l_decl = CONS(ENTITY, new_decl, p_ctxt->l_decl);
560  // the old entity is not used anymore in the module,
561  // in the current statement and in the outermost statement
564  gen_remove(&p_ctxt->l_decl, decl);
565  p_ctxt->changed = true;
566  }
567  } // FOREACH(ENTITY, decl, l_internal_proper_decls)
568 
569  // replace the old entity by the new one in the references of the
570  // outermost statement as well as the loop indices and loop locals
571  // ! does not change the declarations themselves
572  replace_entities_in_cusq_context(p_ctxt, renamings);
573  // change the declarations in place with new names
574  p_ctxt->changed |=
575  sequence_proper_declarations_rename_in_place(internal_sequence, renamings);
576  hash_table_free(renamings);
577  } // if (p_ctxt->merge_sequences_with_declarations && !ENDP(l_internal_proper_decls))
578 
579  statement first = STATEMENT(CAR(l_stmt_to_be_merged));
580  // Unlink the innermost sequence:
581  sequence_statements(internal_sequence) = NIL;
582  // Keep the sequence:
583  useful_sts = gen_nconc(useful_sts, l_stmt_to_be_merged);
584 
585  pips_debug(3, "2 nested sequences fused...\n");
587  p_ctxt->changed = true;
588  // Think to delete the sequence parent:
589  delete_sts = CONS(STATEMENT, st, delete_sts);
590  // To deal with a pending comment:
591  st = first;
592 
593  } // if (statement_sequence_p(st) && !empty_statement_p(st)...)
594  else {
595  // By default, it should be useful:
596  useful_sts = gen_nconc(useful_sts, CONS(STATEMENT, st, NIL));
597  pips_debug(4, "Statement useful... %zd\n",
598  gen_length(useful_sts));
599  }
600  if (the_comments != NULL) p_ctxt->changed = true;
601  deal_with_pending_comment(st, &the_comments);
602  // free the spine of the list of internal declarations
603  gen_free_list(l_internal_proper_decls);
604  }
605  } // FOREACH(STATEMENT, st, sequence_statements(instruction_sequence(i)))
606 
607  /* Remove the list of unused statements with the
608  statements themselves: */
609  gen_full_free_list(delete_sts);
610 
611  if (the_comments != NULL /* || !ENDP(statement_declarations(s))*/) {
612  /* We have a pending comment we were not able to
613  attach. Create a continue statement to attach it: */
615  deal_with_pending_comment(st, &the_comments);
616  useful_sts = gen_nconc(useful_sts,
617  CONS(STATEMENT, st, NIL));
618  pips_debug(3, "CONTINUE created to add a pending comment...\n");
619  }
620 
621  /* Keep track of declarations within an empty sequence:
622  see C_syntax/block01.c */
623  /*
624  if(ENDP(useful_sts) && !ENDP(statement_declarations(s))) {
625  useful_sts = CONS(STATEMENT, s, NIL); // FI: maybe I should copy s?
626  }
627  */
628 
629  // Remove the old list of statements without the statements:
631  sequence_statements(instruction_sequence(i)) = useful_sts;
632 
633  // for consistency: add new entities to module and current_statement declarations
635  {
636  FOREACH(entity, decl, l_new_decls)
637  {
638  pips_debug(3, "adding new declaration for %s\n", entity_name(decl));
640  p_ctxt->changed = true;
641  }
642  }
643 
644  if (gen_length(useful_sts) == 1
647  /* A sequence of only 1 instruction can be replaced by
648  this instruction, if it has not declarations */
649  statement st = STATEMENT(CAR(useful_sts));
650  // Transfer the deeper statement in the current one:
662  /* Do not forget to adjust the GOTOs pointing on st: */
663  adjust_goto_from_to(st, s);
664  /* Discard the old statement: */
665  free_instruction(i);
666  pips_debug(3, "Sequence with 1 statement replaced by 1 statement...\n");
668  p_ctxt->changed = true;
669  }
670 }
void user_log(const char *format,...)
Definition: message.c:234
value make_value_unknown(void)
Definition: ri.c:2847
void free_instruction(instruction p)
Definition: ri.c:1118
static void deal_with_pending_comment(statement s, string *the_comments)
static int clean_up_fused_sequences
static bool sequence_proper_declarations_rename_in_place(sequence seq, hash_table renamings)
change the declarations of declaration statements directly contained in input sequence according to t...
void adjust_goto_from_to(statement s1, statement s2)
Adjust all the GOTOs pointing s1 to s2:
static void replace_entities_in_cusq_context(cusq_context *p_ctxt, hash_table ht)
replace entities in the module references and loop indices and loop locals stored in the input cusq_c...
static int clean_up_1_statement_sequence
static int clean_up_empty_block_removed
Clean up the sequences and their contents by fusing them or removing useless continues or empty instr...
void gen_full_free_list(list l)
Definition: genClib.c:1023
if(!(yy_init))
Definition: genread_lex.c:1029
void free(void *)
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#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
#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
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
bool empty_statement_or_labelless_continue_p(statement)
Return true if the statement is an empty instruction block without label or a continue without label ...
Definition: statement.c:446
bool unlabelled_statement_p(statement)
Definition: statement.c:402
bool empty_statement_p(statement)
Test if a statement is empty.
Definition: statement.c:391
bool statement_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
string statement_identification(statement)
Like external_statement_identification(), but with internal information, the hexadecimal address of t...
Definition: statement.c:1700
list statement_to_direct_declarations(statement)
Returns the declarations contained directly in a statement s.
Definition: statement.c:3366
bool empty_comments_p(const char *)
Definition: statement.c:107
bool statement_with_empty_comment_p(statement)
Return true if the statement has an empty statement:
Definition: statement.c:126
statement make_plain_continue_statement(void)
Make a simple continue statement to be used as a NOP or ";" in C.
Definition: statement.c:964
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
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
#define pips_internal_error
Definition: misc-local.h:149
#define BLOCK_SEP_CHAR
Definition: naming-local.h:51
#define TOP_LEVEL_MODULE_NAME
Module containing the global variables in Fortran and C.
Definition: naming-local.h:101
#define MODULE_SEP_STRING
Definition: naming-local.h:30
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26
#define string_undefined
Definition: newgen_types.h:40
static char * module
Definition: pips.c:74
#define STATEMENT_NUMBER_UNDEFINED
default values
#define entity_declarations(e)
MISC: newgen shorthands.
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
entity make_entity_copy_with_new_name_and_suffix(entity e, string global_new_name, bool move_initialization_p)
Create a copy of an entity, with (almost) identical type, storage and initial value if move_initializ...
Definition: entity.c:2495
void print_entities(list l)
Definition: entity.c:167
const char * label_local_name(entity e)
END_EOLE.
Definition: entity.c:604
entity make_entity_copy_with_new_name(entity e, string global_new_name, bool move_initialization_p)
Create a copy of an entity, with (almost) identical type, storage and initial value if move_initializ...
Definition: entity.c:2463
void AddLocalEntityToDeclarationsOnly(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:253
#define extensions_undefined
Definition: ri.h:1308
#define value_undefined_p(x)
Definition: ri.h:3017
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define instruction_undefined
Definition: ri.h:1454
#define statement_label(x)
Definition: ri.h:2450
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define entity_name(x)
Definition: ri.h:2790
#define sequence_statements(x)
Definition: ri.h:2360
#define statement_extensions(x)
Definition: ri.h:2464
#define instruction_sequence(x)
Definition: ri.h:1514
#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 extensions_extension(x)
Definition: ri.h:1330
#define statement_number(x)
Definition: ri.h:2452
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
char * strndup(char const *s, size_t n)
A replacement function, for systems that lack strndup.
Definition: strndup.c:26
bool merge_sequences_with_declarations

References AddLocalEntityToDeclarationsOnly(), adjust_goto_from_to(), BLOCK_SEP_CHAR, CAR, cusq_context::changed, clean_up_1_statement_sequence, clean_up_empty_block_removed, clean_up_fused_sequences, concatenate(), CONS, deal_with_pending_comment(), empty_comments_p(), empty_statement_or_labelless_continue_p(), empty_statement_p(), ENDP, ENTITY, entity_declarations, entity_initial, entity_name, entity_undefined, entity_undefined_p, entity_user_name(), extensions_extension, extensions_undefined, FindEntity(), FOREACH, fprintf(), free(), free_instruction(), gen_free_list(), gen_full_free_list(), gen_length(), gen_nconc(), gen_remove(), get_current_module_entity(), HASH_DEFAULT_SIZE, hash_pointer, hash_put(), hash_table_free(), hash_table_make(), ifdebug, instruction_sequence, instruction_sequence_p, instruction_undefined, cusq_context::l_decl, label_local_name(), make_entity_copy_with_new_name(), make_entity_copy_with_new_name_and_suffix(), make_plain_continue_statement(), make_value_unknown(), cusq_context::merge_sequences_with_declarations, module, MODULE_SEP_STRING, NIL, pips_debug, pips_internal_error, print_entities(), replace_entities_in_cusq_context(), sequence_proper_declarations_rename_in_place(), sequence_statements, STATEMENT, statement_comments, statement_declarations, statement_extensions, statement_identification(), statement_instruction, statement_label, statement_number, STATEMENT_NUMBER_UNDEFINED, statement_sequence(), statement_sequence_p(), statement_to_direct_declarations(), statement_with_empty_comment_p(), strdup(), string_undefined, strndup(), TOP_LEVEL_MODULE_NAME, unlabelled_statement_p(), user_log(), and value_undefined_p.

Referenced by clean_up_sequences_internal().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compute_statement_to_goto_table()

void compute_statement_to_goto_table ( statement  s)

Since clean_up_sequences() is called before the controlizer, there may be some GOTO.

GOTOs are in fact pointer to the target statement, hence when target statements are moved around, some GOTOs need to be updated. For this purpose, we build a list of GOTOs per target statement.

Definition at line 257 of file clean_up_sequences.c.

258 {
259  pips_assert("Map statement_to_goto_table should be uninitialized.\n",
260  statement_to_goto_table == NULL);
261 
264 }
bool statement_to_goto_table_flt(instruction i)
End: clean up sequences context.
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define instruction_domain
newgen_functional_domain_defined
Definition: ri.h:202

References gen_null(), gen_recurse, hash_pointer, hash_table_make(), instruction_domain, pips_assert, statement_to_goto_table, and statement_to_goto_table_flt().

Referenced by clean_up_sequences_internal().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cusq_ctxt_init()

static void cusq_ctxt_init ( statement  s,
cusq_context p_ctxt 
)
static

Definition at line 133 of file clean_up_sequences.c.

134 {
136  get_bool_property("CLEAN_UP_SEQUENCES_WITH_DECLARATIONS");
137  p_ctxt->l_ref = NIL;
138  p_ctxt->l_loops = NIL;
139  p_ctxt->l_decl = NIL;
140  p_ctxt->changed = false;
141 
143  {
145  s, p_ctxt,
149  NULL);
150  p_ctxt->l_decl = statement_to_declarations(s);
151  // gen_copy_seq(statement_declarations(s));
152  }
153 
154  ifdebug(1)
155  {
156  pips_debug(1, "outermost declarations:");
157  print_entities(p_ctxt->l_decl);
158  fprintf(stderr, "\n");
159  pips_debug(1, "%s merge sequences with declarations\n",
160  p_ctxt->merge_sequences_with_declarations? "":"do not");
161  }
162 }
static bool store_declarations_references(statement st, cusq_context *p_ctxt)
static bool store_reference(reference ref, cusq_context *p_ctxt)
static bool store_loops(loop l, cusq_context *p_ctxt)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
list statement_to_declarations(void *)
Get a list of all variables declared recursively within a statement.
Definition: statement.c:3253
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338

References cusq_context::changed, fprintf(), gen_context_multi_recurse(), gen_null(), get_bool_property(), ifdebug, cusq_context::l_decl, cusq_context::l_loops, cusq_context::l_ref, loop_domain, cusq_context::merge_sequences_with_declarations, NIL, pips_debug, print_entities(), reference_domain, statement_domain, statement_to_declarations(), store_declarations_references(), store_loops(), and store_reference().

Referenced by clean_up_sequences_internal().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cusq_ctxt_reset()

static void cusq_ctxt_reset ( cusq_context p_ctxt)
static

Definition at line 165 of file clean_up_sequences.c.

166 {
167  gen_free_list(p_ctxt->l_loops);
168  p_ctxt->l_loops = NIL;
169 
170  gen_free_list(p_ctxt->l_ref);
171  p_ctxt->l_ref = NIL;
172 
173  gen_free_list(p_ctxt->l_decl);
174  p_ctxt->l_decl = NIL;
175 }

References gen_free_list(), cusq_context::l_decl, cusq_context::l_loops, cusq_context::l_ref, and NIL.

Referenced by clean_up_sequences_internal().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ deal_with_pending_comment()

static void deal_with_pending_comment ( statement  s,
string the_comments 
)
static

There is a pending comment to be added on this statement:

Definition at line 305 of file clean_up_sequences.c.

306 {
307  if (*the_comments != NULL) {
308  /* There is a pending comment to be added on this statement: */
309  insert_comments_to_statement(s, *the_comments);
310  free(*the_comments);
311  *the_comments = NULL;
312  }
313 }
void insert_comments_to_statement(statement, const char *)
Insert a comment string (if non empty) at the beginning of the comments of a statement.
Definition: statement.c:1916

References free(), and insert_comments_to_statement().

Referenced by clean_up_sequences_rewrite().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ discard_statement_to_goto_table()

void discard_statement_to_goto_table ( void  )

Discard the statement_to_goto_table map:

Definition at line 269 of file clean_up_sequences.c.

270 {
271  HASH_MAP(k, v, {
272  // Discard every GOTO list:
273  gen_free_list((list) v);
277 }
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60

References gen_free_list(), HASH_MAP, hash_table_free(), and statement_to_goto_table.

Referenced by clean_up_sequences_internal().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ display_clean_up_sequences_statistics()

void display_clean_up_sequences_statistics ( void  )

Definition at line 62 of file clean_up_sequences.c.

63 {
64  if (get_bool_property("CLEAN_UP_SEQUENCES_DISPLAY_STATISTICS")
65  &&
69  user_log("Statistics about cleaning up sequences:\n");
71  user_log("\t%d empty sequence%s or useless CONTINUE removed.\n",
73  clean_up_empty_block_removed==1? "" : "s");
75  user_log("\t%d %s been fused.\n",
77  clean_up_fused_sequences==1? "sequence has" : "sequences have");
79  user_log("\t%d sequence%s of only 1 statement have been removed.\n",
81  clean_up_1_statement_sequence==1? "" : "s");
82  }
83 }

References clean_up_1_statement_sequence, clean_up_empty_block_removed, clean_up_fused_sequences, get_bool_property(), and user_log().

Referenced by clean_up_sequences().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ initialize_clean_up_sequences_statistics()

void initialize_clean_up_sequences_statistics ( void  )

Definition at line 54 of file clean_up_sequences.c.

References clean_up_1_statement_sequence, clean_up_empty_block_removed, and clean_up_fused_sequences.

Referenced by clean_up_sequences().

+ Here is the caller graph for this function:

◆ replace_entities_in_cusq_context()

static void replace_entities_in_cusq_context ( cusq_context p_ctxt,
hash_table  ht 
)
static

replace entities in the module references and loop indices and loop locals stored in the input cusq_context using the input old/new entities mapping

Definition at line 182 of file clean_up_sequences.c.

183 {
184  FOREACH(REFERENCE, ref, p_ctxt->l_ref)
185  {
186  entity new_ent = hash_get(ht, reference_variable(ref));
187  if (new_ent != HASH_UNDEFINED_VALUE)
188  {
189  pips_debug(6, "new entity found: %s \n", entity_name(new_ent));
190  reference_variable(ref) = new_ent;
191  p_ctxt->changed = true;
192  }
193  }
194 
195  FOREACH(LOOP, l, p_ctxt->l_loops)
196  {
197  entity new_index = hash_get(ht, loop_index(l));
198  if (new_index != entity_undefined)
199  {
200  loop_index(l) = new_index;
201  p_ctxt->changed = true;
202  }
203 
204  for(list l_locals = loop_locals(l); !ENDP(l_locals); POP(l_locals))
205  {
206  entity new_local = hash_get(ht, ENTITY(CAR(l_locals)));
207  if (new_local != entity_undefined)
208  {
209  CAR(l_locals).p = (gen_chunkp) new_local;
210  p_ctxt->changed = true;
211  }
212  }
213  }
214 }
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
union gen_chunk * gen_chunkp
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#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 LOOP(x)
LOOP.
Definition: ri.h:1606
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
#define reference_variable(x)
Definition: ri.h:2326
#define loop_locals(x)
Definition: ri.h:1650
#define loop_index(x)
Definition: ri.h:1640

References CAR, cusq_context::changed, ENDP, ENTITY, entity_name, entity_undefined, FOREACH, hash_get(), HASH_UNDEFINED_VALUE, cusq_context::l_loops, cusq_context::l_ref, LOOP, loop_index, loop_locals, pips_debug, POP, ref, REFERENCE, and reference_variable.

Referenced by clean_up_sequences_rewrite().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sequence_proper_declarations_rename_in_place()

static bool sequence_proper_declarations_rename_in_place ( sequence  seq,
hash_table  renamings 
)
static

change the declarations of declaration statements directly contained in input sequence according to the input old/new entity mapping

Parameters
seqis the input sequence
renamingsis an old/new entity mapping

Definition at line 323 of file clean_up_sequences.c.

324 {
325  bool changed = false;
326 
328  {
330  {
331  list l_decl = statement_declarations(stmt);
332  while (!ENDP(l_decl))
333  {
334  entity decl = ENTITY(CAR(l_decl));
335  entity new_decl = hash_get(renamings, decl);
336  if(new_decl != HASH_UNDEFINED_VALUE) // we have found the old declaration
337  {
338  pips_debug(5, "replacing entity %s by %s\n",
339  entity_name(decl), entity_name(new_decl));
340  CAR(l_decl).p = (gen_chunkp) new_decl;
341  changed = true;
342  hash_del(renamings, decl);
343  }
344  POP(l_decl);
345  }
346  }
347  }
348 
349  return changed;
350 }
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
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
Definition: statement.c:54

References CAR, declaration_statement_p(), ENDP, ENTITY, entity_name, FOREACH, hash_del(), hash_get(), HASH_UNDEFINED_VALUE, pips_debug, POP, sequence_statements, STATEMENT, and statement_declarations.

Referenced by clean_up_sequences_rewrite().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ statement_to_goto_table_flt()

bool statement_to_goto_table_flt ( instruction  i)

End: clean up sequences context.

Add a couple (statement -> GOTO) to the map statement_to_goto_table:

Definition at line 221 of file clean_up_sequences.c.

222 {
223  if (instruction_goto_p(i))
224  {
226 
227  pips_debug(7, "Adding GOTO from instruction %p to statement %p.\n",
228  i, s);
229 
230  if (!hash_defined_p(statement_to_goto_table, (char *) s)) {
232  (char *) s,
233  (char *) CONS(INSTRUCTION, i, NIL));
234  }
235  else {
237  (char *) s,
238  (char *) CONS(INSTRUCTION,
239  i,
241  (char *) s)));
242  }
243  // There is nothing to recurse into:
244  return false;
245  }
246  return true;
247 }
void hash_update(hash_table htp, const void *key, const void *val)
update key->val in htp, that MUST be pre-existent.
Definition: hash.c:491
#define INSTRUCTION(x)
INSTRUCTION.
Definition: ri.h:1448
#define instruction_goto_p(x)
Definition: ri.h:1524

References CONS, hash_defined_p(), hash_get(), hash_put(), hash_update(), INSTRUCTION, instruction_goto, instruction_goto_p, NIL, pips_debug, and statement_to_goto_table.

Referenced by compute_statement_to_goto_table().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ store_declarations_references()

static bool store_declarations_references ( statement  st,
cusq_context p_ctxt 
)
static

Definition at line 114 of file clean_up_sequences.c.

115 {
116  if (declaration_statement_p(st))
117  {
119  {
120  value init_val = entity_initial(decl);
121  if (! value_undefined_p(init_val))
122  {
123  gen_context_recurse(init_val, p_ctxt,
125  }
126  }
127  }
128  return true;
129 }
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758

References declaration_statement_p(), ENTITY, entity_initial, FOREACH, gen_context_recurse, gen_null2(), reference_domain, statement_declarations, store_reference(), and value_undefined_p.

Referenced by cusq_ctxt_init().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ store_loops()

static bool store_loops ( loop  l,
cusq_context p_ctxt 
)
static

Definition at line 107 of file clean_up_sequences.c.

108 {
109  p_ctxt->l_loops = CONS(LOOP, l, p_ctxt->l_loops);
110  return true;
111 }

References CONS, cusq_context::l_loops, and LOOP.

Referenced by cusq_ctxt_init().

+ Here is the caller graph for this function:

◆ store_reference()

static bool store_reference ( reference  ref,
cusq_context p_ctxt 
)
static

Definition at line 100 of file clean_up_sequences.c.

101 {
102  p_ctxt->l_ref = CONS(REFERENCE, ref, p_ctxt->l_ref);
103  return true;
104 }

References CONS, cusq_context::l_ref, ref, and REFERENCE.

Referenced by cusq_ctxt_init(), and store_declarations_references().

+ Here is the caller graph for this function:

Variable Documentation

◆ clean_up_1_statement_sequence

int clean_up_1_statement_sequence
static

◆ clean_up_empty_block_removed

int clean_up_empty_block_removed
static

Clean up the sequences and their contents by fusing them or removing useless continues or empty instructions.

Ronan Keryell To store the statistics:

Definition at line 47 of file clean_up_sequences.c.

Referenced by clean_up_sequences_rewrite(), display_clean_up_sequences_statistics(), and initialize_clean_up_sequences_statistics().

◆ clean_up_fused_sequences

◆ statement_to_goto_table