PIPS
full_spaghettify.c File Reference
#include <stdio.h>
#include <ctype.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "effects.h"
#include "resources.h"
#include "misc.h"
#include "ri-util.h"
#include "prettyprint.h"
#include "effects-util.h"
#include "pipsdbm.h"
#include "text-util.h"
#include "dg.h"
#include "control.h"
#include "callgraph.h"
#include "spaghettify.h"
#include "phrase_tools.h"
+ Include dependency graph for full_spaghettify.c:

Go to the source code of this file.

Functions

static control full_spaghettify_statement (statement stat, const char *module_name, unstructured u, control current_control, control next_control)
 The spaghettifier is used in context of PHRASE project while creating "Finite State Machine"-like code portions in order to synthetise them in reconfigurables units. More...
 
static control connect_unstructured (statement unstructured_statement, control current_control, control next_control)
 This function connect the unstructured unstructured_statement to the current Control Flow Graph between control nodes current_control and next_control. More...
 
static void reduce_sequence (control current_control, sequence seq, control *new_entry, control *new_exit)
 This function reduce the sequence seq at the position in the control graph indicated by control current_control. More...
 
static void flatten_unstructured (unstructured the_unstructured)
 This function takes as entry an unstructured and flatten it: More...
 
static control replace_control_with_unstructured (unstructured the_unstructured, control current_control)
 This function connect the unstructured the_unstructured to the current Control Flow Graph at the place of specified control the_control. More...
 
static statement full_spaghettify_module (statement module_statement, const char *module_name)
 
bool full_spaghettify (const char *module_name)
 full_spaghettify.c More...
 

Function Documentation

◆ connect_unstructured()

static control connect_unstructured ( statement  unstructured_statement,
control  current_control,
control  next_control 
)
static

This function connect the unstructured unstructured_statement to the current Control Flow Graph between control nodes current_control and next_control.

pips_assert("Entry with no predecessor in CONNECT_UNSTRUCTURED", gen_length(control_predecessors(entry)) == 0);

Definition at line 388 of file full_spaghettify.c.

391 {
392  unstructured the_unstructured
393  = instruction_unstructured(statement_instruction(unstructured_statement));
394  control exit;
395 
396  pips_assert("Control with 1 successors in CONNECT_UNSTRUCTURED",
397  gen_length(control_successors(current_control)) == 1);
398  pips_assert("Control with 1 predecessor in CONNECT_UNSTRUCTURED",
399  gen_length(control_predecessors(next_control)) == 1);
400  pips_assert("Control connections in CONNECT_UNSTRUCTURED",
401  CONTROL(gen_nth(0,control_successors(current_control)))
402  == next_control);
403 
404  exit = unstructured_exit (the_unstructured);
405 
406  pips_assert("Exit with no successors in CONNECT_UNSTRUCTURED",
408  /* pips_assert("Entry with no predecessor in CONNECT_UNSTRUCTURED",
409  gen_length(control_predecessors(entry)) == 0); */
410 
411  pips_debug(5,"connect_unstructured BEFORE flatten_unstructured()\n");
412  ifdebug(5) {
413  print_statement (unstructured_statement);
414  }
415 
416  flatten_unstructured (the_unstructured);
417 
418  pips_debug(5,"connect_unstructured AFTER flatten_unstructured()\n");
419  ifdebug(5) {
420  print_statement (unstructured_statement);
421  }
422 
423  exit = unstructured_exit (the_unstructured);
424  unlink_2_control_nodes (current_control, next_control);
425  link_2_control_nodes (current_control, unstructured_entry(the_unstructured));
426  link_2_control_nodes (unstructured_exit(the_unstructured), next_control);
427 
428  return exit;
429 }
static void flatten_unstructured(unstructured the_unstructured)
This function takes as entry an unstructured and flatten it:
void unlink_2_control_nodes(control source, control target)
Remove all edged between 2 control nodes.
Definition: control.c:1276
void link_2_control_nodes(control source, control target)
Add an edge between 2 control nodes.
Definition: control.c:1193
size_t gen_length(const list l)
Definition: list.c:150
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#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 exit(code)
Definition: misc-local.h:54
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
#define control_predecessors(x)
Definition: ri.h:943
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
#define control_successors(x)
Definition: ri.h:945
#define unstructured_exit(x)
Definition: ri.h:3006
#define unstructured_entry(x)
Definition: ri.h:3004
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_unstructured(x)
Definition: ri.h:1532
#define ifdebug(n)
Definition: sg.c:47

References CONTROL, control_predecessors, control_successors, exit, flatten_unstructured(), gen_length(), gen_nth(), ifdebug, instruction_unstructured, link_2_control_nodes(), pips_assert, pips_debug, print_statement(), statement_instruction, unlink_2_control_nodes(), unstructured_entry, and unstructured_exit.

Referenced by full_spaghettify_statement().

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

◆ flatten_unstructured()

static void flatten_unstructured ( unstructured  the_unstructured)
static

This function takes as entry an unstructured and flatten it:

  • by reducing hierarchical unstructured
  • by reducing sequence statement (the sequence control node is replaced by a sequence of new control nodes formed with the statements inside the sequence)

Repeat until there is no more sequences to reduce and unstructured to flatten

First, check all the sequences to reduce

Do the job on the sequences

ree_control(current_control);

Check the unstructured to flatten

Do the job on the unstructured

ree_control(current_control);

Definition at line 271 of file full_spaghettify.c.

272 {
273  list blocs = NIL;
274  list sequences_to_reduce = NIL;
275  list unstructured_to_flatten = NIL;
276  int nb_of_sequences_to_reduce;
277  int nb_of_unstructured_to_flatten;
278  int debug_iteration = 0;
279 
280  /* Repeat until there is no more sequences to
281  reduce and unstructured to flatten */
282 
283  do {
284 
285  blocs = NIL;
286  debug_iteration++;
287  pips_debug(2,"New iteration %d\n", debug_iteration);
288 
289  sequences_to_reduce = NIL;
290  unstructured_to_flatten = NIL;
291 
292  ifdebug(5) {
293  short_debug_unstructured (the_unstructured, 2);
294  }
295 
296  /* First, check all the sequences to reduce */
297  CONTROL_MAP (current_control, {
298  instruction i;
299  i = statement_instruction(control_statement(current_control));
300  switch (instruction_tag(i)) {
302  {
303  sequences_to_reduce
304  = CONS(CONTROL,
305  current_control,
306  sequences_to_reduce);
307  pips_debug (5, "MARKING SEQUENCE: %p\n", current_control);
308  debug_control ("SEQUENCE: ", current_control, 5);
309  }
310  default:
311  break;
312  }
313  }, unstructured_entry (the_unstructured), blocs);
314 
315  nb_of_sequences_to_reduce = gen_length (sequences_to_reduce);
316 
317  /* Do the job on the sequences */
318  FOREACH(CONTROL, current_control, sequences_to_reduce)
319  {
321  control new_entry_of_imbricated = control_undefined;
322  control new_exit_of_imbricated = control_undefined;
323  pips_debug(2,"Imbricated sequence: REDUCING\n");
324  debug_control ("REDUCE SEQUENCE: ", current_control, 5);
325  reduce_sequence (current_control,
327  &new_entry_of_imbricated,
328  &new_exit_of_imbricated);
329  pips_debug(5,"Entry of imbricated sequence is %p\n",new_entry_of_imbricated);
330  pips_debug(5,"Exit of imbricated sequence is %p\n",new_exit_of_imbricated);
331  if (current_control == unstructured_entry (the_unstructured)) {
332  pips_debug(5,"Changing entry %p for %p\n",
333  unstructured_entry (the_unstructured),
334  new_entry_of_imbricated);
335  unstructured_entry (the_unstructured) = new_entry_of_imbricated;
336  }
337  else if (current_control == unstructured_exit (the_unstructured)) {
338  pips_debug(5,"Changing exit %p for %p\n",
339  unstructured_exit (the_unstructured),
340  new_exit_of_imbricated);
341  unstructured_exit (the_unstructured) = new_exit_of_imbricated;
342  }
343  /*free_control(current_control);*/
344  }
345 
346  /* Check the unstructured to flatten */
347  CONTROL_MAP (current_control, {
349  switch (instruction_tag(i)) {
351  {
352  unstructured_to_flatten
353  = CONS(CONTROL,
354  current_control,
355  unstructured_to_flatten);
356  pips_debug (5, "MARKING UNSTRUCTURED: %p\n", current_control);
357  debug_control ("UNSTRUCTURED: ", current_control, 5);
358  }
359  default:
360  break;
361  }
362  }, unstructured_entry (the_unstructured), blocs);
363 
364  nb_of_unstructured_to_flatten = gen_length (unstructured_to_flatten);
365 
366  /* Do the job on the unstructured */
367  MAP (CONTROL, current_control, {
370  pips_debug(2,"Imbricated unstructured: FLATTENING\n");
371  pips_debug(5,"Flatten unstructured\n");
372  debug_control ("FLATTEN UNSTRUCTURED: ", current_control, 5);
373  replace_control_with_unstructured (u, current_control);
374  /*free_control(current_control);*/
375  }, unstructured_to_flatten);
376 
377  }
378  while (((nb_of_sequences_to_reduce > 0)
379  || (nb_of_unstructured_to_flatten > 0)) && (debug_iteration < 3));
380 
381 }
static void reduce_sequence(control current_control, sequence seq, control *new_entry, control *new_exit)
This function reduce the sequence seq at the position in the control graph indicated by control curre...
static control replace_control_with_unstructured(unstructured the_unstructured, control current_control)
This function connect the unstructured the_unstructured to the current Control Flow Graph at the plac...
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an unstructured.
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#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 MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
void short_debug_unstructured(unstructured, int)
DEBUG FUNCTION: print debugging informations for an unstructured an_unstructured (short version)
Definition: phrase_tools.c:213
void debug_control(const char *, control, int)
DEBUG FUNCTION: print debugging informations for a control a_control.
Definition: phrase_tools.c:134
#define control_undefined
Definition: ri.h:916
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_sequence
Definition: ri.h:1469
#define instruction_tag(x)
Definition: ri.h:1511
#define instruction_sequence(x)
Definition: ri.h:1514
#define control_statement(x)
Definition: ri.h:941
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References CONS, CONTROL, CONTROL_MAP, control_statement, control_undefined, debug_control(), FOREACH, gen_length(), ifdebug, instruction_sequence, instruction_tag, instruction_unstructured, is_instruction_sequence, is_instruction_unstructured, MAP, NIL, pips_debug, reduce_sequence(), replace_control_with_unstructured(), short_debug_unstructured(), statement_instruction, unstructured_entry, and unstructured_exit.

Referenced by connect_unstructured(), and replace_control_with_unstructured().

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

◆ full_spaghettify()

bool full_spaghettify ( const char *  module_name)

full_spaghettify.c

get the resources

Now do the job

Reorder the module, because new statements have been added

Restructure the module

Reorder the module, because new statements have been added

ATTENTION after simple_restructure_statement, statement stat is not longer a unstructured, but may be a sequence !!!

update/release resources

Parameters
module_nameodule_name

Definition at line 603 of file full_spaghettify.c.

604 {
605  /* get the resources */
606  statement stat = (statement) db_get_memory_resource(DBR_CODE,
607  module_name,
608  true);
609 
612 
613  debug_on("SPAGUETTIFY_DEBUG_LEVEL");
614 
615  /* Now do the job */
616  stat = full_spaghettify_module(stat, module_name);
617 
618  pips_assert("Statement is consistent after FULL_SPAGUETTIFY",
619  statement_consistent_p(stat));
620 
621  pips_assert("Unstructured is consistent after FULL_SPAGUETTIFY",
623 
624  /* Reorder the module, because new statements have been added */
625  module_reorder(stat);
626 
627  ifdebug(5) {
628  pips_debug(5,"====================================================\n");
629  pips_debug(5,"Statement BEFORE simple_restructure_statement\n");
630  print_statement (stat);
631  }
632 
633  /* Restructure the module */
635 
636  ifdebug(5) {
637  pips_debug(5,"====================================================\n");
638  pips_debug(5,"Statement AFTER simple_restructure_statement\n");
639  print_statement (stat);
640  }
641 
642  /* Reorder the module, because new statements have been added */
643  module_reorder(stat);
644 
645  pips_assert("Statement is consistent after FULL_SPAGUETTIFY",
646  statement_consistent_p(stat));
647 
648  /**
649  * ATTENTION
650  * after simple_restructure_statement, statement stat is
651  * not longer a unstructured, but may be a sequence !!!
652  */
653 
654  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module_name, stat);
655  DB_PUT_MEMORY_RESOURCE(DBR_CALLEES, module_name,
656  compute_callees(stat));
657 
658  /* update/release resources */
661 
662  debug_off();
663 
664  return true;
665 }
bool unstructured_consistent_p(unstructured p)
Definition: ri.c:2751
bool statement_consistent_p(statement p)
Definition: ri.c:2195
callees compute_callees(const statement stat)
Recompute the callees of a module statement.
Definition: callgraph.c:355
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
void simple_restructure_statement(statement)
A simple cleaning of the control graph without major topological restructuring.
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
static statement full_spaghettify_module(statement module_statement, const char *module_name)
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
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
unstructured statement_unstructured(statement stat)
Get the unstructured of a statement.
Definition: statement.c:1416
#define debug_on(env)
Definition: misc-local.h:157
#define debug_off()
Definition: misc-local.h:160
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479

References compute_callees(), db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, full_spaghettify_module(), ifdebug, module_name(), module_name_to_entity(), module_reorder(), pips_assert, pips_debug, print_statement(), reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), simple_restructure_statement(), statement_consistent_p(), statement_unstructured(), and unstructured_consistent_p().

+ Here is the call graph for this function:

◆ full_spaghettify_module()

static statement full_spaghettify_module ( statement  module_statement,
const char *  module_name 
)
static

Definition at line 93 of file full_spaghettify.c.

95 {
96  statement returned_statement;
97  unstructured new_unstructured;
98  instruction unstructured_instruction;
99  control entry;
100  control exit;
101  list blocs = NIL ;
102  int stat_number;
103  int stat_ordering;
104 
106  (entity_empty_label()), NIL, NIL);
108  (entity_empty_label()), NIL, NIL);
109  link_2_control_nodes (entry, exit);
110  new_unstructured
111  = make_unstructured(entry, exit);
112 
113  unstructured_instruction = make_instruction(is_instruction_unstructured,
114  new_unstructured);
115 
116 
117  stat_number = statement_number(module_statement);
118  stat_ordering = statement_ordering(module_statement);
119 
121  module_name,
122  new_unstructured,
123  entry,
124  exit);
125 
126  returned_statement = make_statement(entity_empty_label(),
127  stat_number,
128  stat_ordering,
130  unstructured_instruction,
131  NIL, NULL,
133 
134  pips_assert("Statement is consistent after FULL_SPAGUETTIFY",
135  statement_consistent_p(returned_statement));
136 
137  ifdebug(2) {
138  CONTROL_MAP (current_control, {
139  pips_assert("Statement is consistent after FULL_SPAGUETTIFY",
140  statement_consistent_p(control_statement(current_control)));
141  debug_control("FSM STATE: Module control =======================================",current_control, 2);
142  }, entry, blocs);
143  }
144  return returned_statement;
145 }
unstructured make_unstructured(control a1, control a2)
Definition: ri.c:2778
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
synchronization make_synchronization_none(void)
Definition: ri.c:2424
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
static statement module_statement
Definition: alias_check.c:125
static control full_spaghettify_statement(statement stat, const char *module_name, unstructured u, control current_control, control next_control)
The spaghettifier is used in context of PHRASE project while creating "Finite State Machine"-like cod...
statement make_continue_statement(entity)
Definition: statement.c:953
#define empty_comments
Empty comments (i.e.
entity entity_empty_label(void)
Definition: entity.c:1105
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_extensions(x)
Definition: ri.h:2464
#define statement_number(x)
Definition: ri.h:2452

References CONTROL_MAP, control_statement, debug_control(), empty_comments, entity_empty_label(), exit, full_spaghettify_statement(), ifdebug, is_instruction_unstructured, link_2_control_nodes(), make_continue_statement(), make_control(), make_instruction(), make_statement(), make_synchronization_none(), make_unstructured(), module_name(), module_statement, NIL, pips_assert, statement_consistent_p(), statement_extensions, statement_number, and statement_ordering.

Referenced by full_spaghettify().

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

◆ full_spaghettify_statement()

static control full_spaghettify_statement ( statement  stat,
const char *  module_name,
unstructured  module_unstructured,
control  current_control,
control  next_control 
)
static

The spaghettifier is used in context of PHRASE project while creating "Finite State Machine"-like code portions in order to synthetise them in reconfigurables units.

This function recursively takes the stat statement and transform the Control Flow Graph module_unstructured in order to generate equivalent code.

This phases transforms all the module in a unique unstructured statement where all the control nodes are:

  • CALL
  • or TEST
  • or SEQUENCE

In fact the module becomes a sequence statement with a beginning statement, the unstructured statement and a final statement

full_spaghettify > MODULE.code < PROGRAM.entities < MODULE.code

The statement to transform is assumed to be executed between controls current_control and next_control.

Generated unstructured is equivalent to a FSM where all the states are the different nodes of the Control Flow Graph

This function return the control node corresponding to the new position in the Control Flow Graph

ree_statement(stat);

Definition at line 498 of file full_spaghettify.c.

503 {
504 
506 
507  ifdebug(2) {
508  debug_statement("FULL_SPAGHETTIFY: Module statement: =====================================", stat, 2);
509 
510  pips_assert("Control with 1 successors in FULL_SPAGHETTIFY",
511  gen_length(control_successors(current_control)) == 1);
512  pips_assert("Control with 1 predecessor in FULL_SPAGHETTIFY",
513  gen_length(control_predecessors(next_control)) == 1);
514  pips_assert("Control connections in FULL_SPAGHETTIFY",
515  CONTROL(gen_nth(0,control_successors(current_control)))
516  == next_control);
517  }
518 
519  switch (instruction_tag(i)) {
520  case is_instruction_test:
521  {
522  pips_debug(2, "full_spaghettify_statement: TEST\n");
523  return
525  current_control,
526  next_control);
527  break;
528  }
530  {
532  control last_control = current_control;
533  pips_debug(2, "full_spaghettify_statement: SEQUENCE\n");
534  MAP(STATEMENT, current_stat,
535  {
536  last_control = full_spaghettify_statement (current_stat,
537  module_name,
538  module_unstructured,
539  last_control,
540  next_control);
541  }, sequence_statements(seq));
542  /*free_statement(stat);*/
543  return last_control;
544  break;
545  }
546  case is_instruction_loop: {
547  pips_debug(2, "full_spaghettify_statement: LOOP\n");
548  return
550  current_control,
551  next_control);
552  break;
553  }
555  pips_debug(2, "full_spaghettify_statement: WHILELOOP\n");
556  return
558  current_control,
559  next_control);
560  break;
561  }
562  case is_instruction_forloop: {
563  pips_debug(2, "full_spaghettify_statement: FORLOOP\n");
565  current_control,
566  next_control);
567  break;
568  }
569  case is_instruction_call: {
570  control new_control = make_control (stat, NIL, NIL);
571  pips_debug(2, "full_spaghettify_statement: CALL\n");
572  unlink_2_control_nodes (current_control, next_control);
573  link_2_control_nodes (current_control, new_control);
574  link_2_control_nodes (new_control, next_control);
575  return new_control;
576  break;
577  }
579  pips_debug(2, "full_spaghettify_statement: UNSTRUCTURED\n");
580  ifdebug(5) {
581  print_statement (stat);
582  }
583  return
584  connect_unstructured (stat,
585  current_control,
586  next_control);
587  break;
588  }
589  default:
590  pips_user_warning("full_spaghettify_statement: UNDEFINED\n");
591  return current_control;
592  break;
593  }
594 
595 
596 }
statement spaghettify_forloop(statement stat, const char *module_name)
This function takes the statement stat as parameter and return a new spaghettized statement,...
static control connect_unstructured(statement unstructured_statement, control current_control, control next_control)
This function connect the unstructured unstructured_statement to the current Control Flow Graph betwe...
statement spaghettify_loop(statement stat, const char *module_name)
This function takes the statement stat as parameter and return a new spaghettized statement,...
#define pips_user_warning
Definition: misc-local.h:146
statement spaghettify_test(statement, const char *)
test_spaghettify.c
void debug_statement(const char *, statement, int)
DEBUG FUNCTION: print debugging informations for a statement stat.
Definition: phrase_tools.c:111
statement spaghettify_whileloop(statement, const char *)
whileloop_spaghettify.c
@ is_instruction_whileloop
Definition: ri.h:1472
@ 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 sequence_statements(x)
Definition: ri.h:2360
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413

References connect_unstructured(), CONTROL, control_predecessors, control_successors, debug_statement(), gen_length(), gen_nth(), ifdebug, instruction_sequence, instruction_tag, is_instruction_call, is_instruction_forloop, is_instruction_loop, is_instruction_sequence, is_instruction_test, is_instruction_unstructured, is_instruction_whileloop, link_2_control_nodes(), make_control(), MAP, module_name(), NIL, pips_assert, pips_debug, pips_user_warning, print_statement(), sequence_statements, spaghettify_forloop(), spaghettify_loop(), spaghettify_test(), spaghettify_whileloop(), STATEMENT, statement_instruction, and unlink_2_control_nodes().

Referenced by full_spaghettify_module().

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

◆ reduce_sequence()

static void reduce_sequence ( control  current_control,
sequence  seq,
control new_entry,
control new_exit 
)
static

This function reduce the sequence seq at the position in the control graph indicated by control current_control.

The sequence is reduced by the creation of new control nodes corresponding to all the statements in the sequence. In addition new_entry and new_exit control pointers are updated according to the transformation. NOTE: this function don't do recursively the job, but is generally called by flatten_unstructured which do the job recursively.

Conserve lists of predecessors and successors

Deconnect all the predecessors

Deconnect all the successors

We iterate on each statement in the sequence

We build a new control node from current statement

For the first statement...

Reconnect all the predecessors

ATTENTION link_2_control_nodes add to the list at the first position, so we need to reconnect in the reverse order

Reconnect all the successors

ATTENTION link_2_control_nodes add to the list at the first position, so we need to reconnect in the reverse order

If this is not the first statement, we have to link it with the previous one

Deconnect all the OLD successors

Reconnect all the NEW successors

ATTENTION link_2_control_nodes add to the list at the first position, so we need to reconnect in the reverse order

Definition at line 156 of file full_spaghettify.c.

160 {
161  control first_control = NULL;
162  control last_control = NULL;
163  control new_control = NULL;
164  bool is_first_control;
165  int i;
166 
167  if(gen_length(sequence_statements(seq)) == 0)
168  {
169  *new_entry = control_undefined;
170  *new_exit = control_undefined;
171  return;
172  }
173 
174  /* Conserve lists of predecessors and successors */
175  list predecessors = gen_copy_seq (control_predecessors(current_control));
176  list successors = gen_copy_seq (control_successors(current_control));
177 
178  pips_debug(5,"CONTROL [%p]\n", current_control);
179  ifdebug(5) {
180  print_statement (control_statement(current_control));
181  }
182 
183  /* Deconnect all the predecessors */
184  for (i=0; i<(int)gen_length(predecessors); i++) {
185  pips_debug(5,"Unlink predecessor [%p-%p]\n",
187  current_control);
188  unlink_2_control_nodes (CONTROL(gen_nth(i,predecessors)), current_control);
189  }
190 
191  /* Deconnect all the successors */
192  for (i=0; i<(int)gen_length(successors); i++) {
193  pips_debug(5,"Unlink successor [%p-%p]\n",
194  current_control,
196  unlink_2_control_nodes (current_control, CONTROL(gen_nth(i,successors)));
197  }
198 
199  is_first_control = true;
200 
201  /* We iterate on each statement in the sequence */
202  FOREACH(STATEMENT, current_stat, sequence_statements(seq))
203  {
204  /* We build a new control node from current statement */
205  new_control = make_control (current_stat, NIL, NIL);
206  ifdebug(5) {
207  print_statement (current_stat);
208  }
209  if (is_first_control) {
210  /* For the first statement... */
211  first_control = new_control;
212  is_first_control = false;
213  pips_debug(5,"First control %p\n", first_control);
214  *new_entry = first_control;
215  /* Reconnect all the predecessors */
216  /* ATTENTION link_2_control_nodes add to the list at the first position,
217  so we need to reconnect in the reverse order */
218  for (i=gen_length(predecessors)-1; i>=0; i--) {
219  pips_debug(5,"Relink predecessor [%p-%p]\n",
221  first_control);
223  link_2_control_nodes (c, first_control);
224  }
225  /* Reconnect all the successors */
226  /* ATTENTION link_2_control_nodes add to the list at the first position,
227  so we need to reconnect in the reverse order */
228  for (i=gen_length(successors)-1; i>=0; i--) {
229  pips_debug(5,"Relink successor [%p-%p]\n",
230  first_control,
232  link_2_control_nodes (first_control, CONTROL(gen_nth(i,successors)));
233  }
234  }
235  else {
236  /* If this is not the first statement, we have to link
237  it with the previous one */
238  link_2_control_nodes (last_control, new_control);
239  pips_debug(5,"Other control %p [%p-%p]\n",
240  new_control, last_control, new_control);
241  /* Deconnect all the OLD successors */
242  for (i=0; i<(int)gen_length(successors); i++) {
243  pips_debug(5,"Unlink successor [%p-%p]\n",
244  last_control,
246  unlink_2_control_nodes (last_control, CONTROL(gen_nth(i,successors)));
247  }
248  /* Reconnect all the NEW successors */
249  /* ATTENTION link_2_control_nodes add to the list at the first position,
250  so we need to reconnect in the reverse order */
251  for (i=gen_length(successors)-1; i>=0; i--) {
252  pips_debug(5,"Relink successor [%p-%p]\n",
253  new_control,
255  link_2_control_nodes (new_control, CONTROL(gen_nth(i,successors)));
256  }
257  }
258  last_control = new_control;
259  *new_exit = new_control;
260  }
261 }
void const char const char const int
static list predecessors(statement st, graph tg)
static list successors(list l)
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501

References CONTROL, control_predecessors, control_statement, control_successors, control_undefined, FOREACH, gen_copy_seq(), gen_length(), gen_nth(), ifdebug, int, link_2_control_nodes(), make_control(), NIL, pips_debug, predecessors(), print_statement(), sequence_statements, STATEMENT, successors(), and unlink_2_control_nodes().

Referenced by flatten_unstructured().

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

◆ replace_control_with_unstructured()

static control replace_control_with_unstructured ( unstructured  the_unstructured,
control  current_control 
)
static

This function connect the unstructured the_unstructured to the current Control Flow Graph at the place of specified control the_control.

The predecessors and successors will be the same as the_control predecessors and successors. Return the new current control, which is the exit of passed unstructured

Conserve lists of predecessors and successors

Deconnect all the predecessors

Deconnect all the successors

ips_assert("Entry of unstructured has no predecessor", gen_length(control_predecessors(entry)) == 0);

Reconnect all the predecessors

ATTENTION link_2_control_nodes add to the list at the first position, so we need to reconnect in the reverse order

Reconnect all the successors

ATTENTION link_2_control_nodes add to the list at the first position, so we need to reconnect in the reverse order

Definition at line 438 of file full_spaghettify.c.

440 {
441  control entry, exit;
442  int i;
443 
444  /* Conserve lists of predecessors and successors */
445  list predecessors = gen_copy_seq (control_predecessors(current_control));
446  list successors = gen_copy_seq (control_successors(current_control));
447 
448  /* Deconnect all the predecessors */
449  for (i=0; i<(int)gen_length(predecessors); i++) {
450  unlink_2_control_nodes (CONTROL(gen_nth(i,predecessors)), current_control);
451  }
452 
453  /* Deconnect all the successors */
454  for (i=0; i<(int)gen_length(successors); i++) {
455  unlink_2_control_nodes (current_control, CONTROL(gen_nth(i,successors)));
456  }
457 
458  flatten_unstructured (the_unstructured);
459 
460  entry = unstructured_entry (the_unstructured);
461  exit = unstructured_exit (the_unstructured);
462 
463  /*pips_assert("Entry of unstructured has no predecessor",
464  gen_length(control_predecessors(entry)) == 0);*/
465 
466  pips_assert("Exit of unstructured has no successor",
468 
469  /* Reconnect all the predecessors */
470  /* ATTENTION link_2_control_nodes add to the list at the first position,
471  so we need to reconnect in the reverse order */
472  for (i=gen_length(predecessors)-1; i>=0; i--) {
474  }
475 
476  /* Reconnect all the successors */
477  /* ATTENTION link_2_control_nodes add to the list at the first position,
478  so we need to reconnect in the reverse order */
479  for (i=gen_length(successors)-1; i>=0; i--) {
481  }
482 
483  return exit;
484 }

References CONTROL, control_predecessors, control_successors, exit, flatten_unstructured(), gen_copy_seq(), gen_length(), gen_nth(), int, link_2_control_nodes(), pips_assert, predecessors(), successors(), unlink_2_control_nodes(), unstructured_entry, and unstructured_exit.

Referenced by flatten_unstructured().

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