PIPS
Functions to manage control the graph and

unstructured More...

+ Collaboration diagram for Functions to manage control the graph and:

Functions

bool is_control_in_list_p (control c, list cs)
 Test if a control node is in a list of control nodes. More...
 
int occurences_in_control_list (control c, list cs)
 Count the number of occurences of a control node in a list of control nodes. More...
 
void control_list_patch (list l, control c_old, control c_new)
 Replace in a list of control nodes all the instance of a control node by another one. More...
 
void transfer_control_predecessor (control old_node, control new_node, control c)
 Transfer a control node as a predecessor from one node to another one. More...
 
void transfer_control_successor (control old_node, control new_node, control c)
 Transfer a control node as a successor of one node to another one. More...
 
void replace_control_related_to_a_list (control old_node, control new_node, list controls)
 Replace all the references to a control node by a new one in the successors & predecessors of a list of controls. More...
 
void check_control_coherency (control c)
 Test the coherency of a control node network from a control node. More...
 
void print_control_node (control c)
 
void print_control_nodes (list l)
 Display identification of a list of control nodes. More...
 
void display_address_of_control_nodes (list cs)
 Display the adresses a list of control nodes. More...
 
void display_linked_control_nodes (control c)
 Display all the control nodes reached or reachable from c for debugging purpose. More...
 
void remove_unreachable_following_control (control c, control do_not_delete_node, control do_not_delete_node_either)
 Remove all the control nodes (with their statements) from c in the successor tree of c up to the nodes with more than 1 predecessor, that is when it reach another flow. More...
 
void remove_some_unreachable_controls_of_an_unstructured (unstructured u)
 Remove all the control sequences that are unreachable and that begin with a node without any predecessor. More...
 
void remove_all_unreachable_controls_of_an_unstructured (unstructured u)
 Remove all control nodes that are not forward reachable from the entry node. More...
 
void remove_a_control_from_a_list_and_relink (control c, list a_source_control_list_of_c, list a_dest_control_list_of_c, remove_a_control_from_a_list_and_relink_direction which_way)
 Replace each occurence of c in a_source_control_list_of_c with a a_dest_control_list_of_c: More...
 
void remove_a_control_from_an_unstructured (control c)
 Remove a control node from a control graph. More...
 
void remove_a_control_from_an_unstructured_without_relinking (control c)
 It removes a control node from its successor and predecessor. More...
 
void discard_an_unstructured_without_its_statements (unstructured u)
 Used to discard an unstructured without touching its statements. More...
 
void free_a_control_without_its_statement (control c)
 Remove a control node without touching its statement, its predecessors and successors, if any. More...
 
void discard_a_control_sequence_without_its_statements (control begin, control end)
 Remove a control sequence without touching its statements. More...
 
list generate_a_statement_list_from_a_control_sequence (control begin, control end)
 Take a control sequence and return a list of all the statements in the sequence (in the same order... More...
 
void link_2_control_nodes (control source, control target)
 Add an edge between 2 control nodes. More...
 
void link_3_control_nodes (control c_test, control c_then, control c_else)
 Add an edge between 2 control nodes. More...
 
void unlink_2_control_nodes (control source, control target)
 Remove all edged between 2 control nodes. More...
 
void insert_control_in_arc (control c, control before, control after)
 Insert a control node between 2 connected control nodes. More...
 
void fuse_2_control_nodes (control first, control second)
 Fuse a 2 control nodes. More...
 

Detailed Description

unstructured

Function Documentation

◆ check_control_coherency()

void check_control_coherency ( control  c)

Test the coherency of a control node network from a control node.

Do not verify the fact that nodes could appear twice in the case of unstructured tests.

Parameters
cis the control node we want to start the verification from

Test the coherency of the successors

if (!is_control_in_list_p(ctl, control_predecessors(cc))) {

Test the coherency of the predecessors

if (!is_control_in_list_p(ctl, control_successors(cc))) {

Check that the statement are consistent

Check that two nodes do not point towards the same statement as this makes label resolution ambiguous

Definition at line 487 of file control.c.

488 {
489  list blocs = NIL;
490  int i1, i2;
491  set stmts = set_make(set_pointer);
492 
494 
495  CONTROL_MAP(ctl, {
496 
497  /* Test the coherency of the successors */
498  MAP(CONTROL, cc, {
499  /* if (!is_control_in_list_p(ctl, control_predecessors(cc))) { */
502  if(i1==0) {
503  pips_debug(0, "Control node %p not in the predecessor list of %p\n", ctl, cc);
504  }
505  else {
506  pips_debug(0, "Control %p occurs %d times in the predecessor list of %p"
507  " while control %p occurs %d times in the successor list of %p\n",
508  ctl, i1, cc, cc, i2, ctl);
509  }
510  ifdebug(8)
511  pips_assert("Control is correct", false);
512  }
513  }, control_successors(ctl));
514 
515  /* Test the coherency of the predecessors */
516  MAP(CONTROL, cc, {
517  /* if (!is_control_in_list_p(ctl, control_successors(cc))) { */
520  bool consistent_p = false;
521  if(i1==0) {
522  pips_debug(0, "Control node %p not in the successor list of %p\n", ctl, cc);
523  }
524  else {
525  if(statement_test_p(control_statement(cc)) && i1>=2 && i2==1) {
526  consistent_p = true;
527  }
528  else {
529  pips_debug(0, "Control %p occurs %d times in the successor list of %p"
530  " while control %p occurs %d times in the predecessor list of %p\n",
531  ctl, i1, cc, cc, i2, ctl);
532  }
533  }
534  ifdebug(8) {
535  if(!consistent_p) {
536  pips_debug(8, "control %p is not correct\n", cc);
537  pips_assert("Control is correct", consistent_p);
538  }
539  }
540  }
541  }, control_predecessors(ctl));
542 
543  /* Check that the statement are consistent */
545 
546  /* Check that two nodes do not point towards the same
547  statement as this makes label resolution ambiguous */
548  if(set_belong_p(stmts, control_statement(ctl))) {
549  fprintf(stderr, "Statement %p is pointed by two different control nodes\n", control_statement(ctl));
550  pips_assert("each statement appears in at most one control node", false);
551  }
552  else
553  stmts = set_add_element(stmts, stmts, (void *) control_statement(ctl));
554  }, c, blocs);
555 
556  set_free(stmts);
557  gen_free_list(blocs);
558 }
bool statement_consistent_p(statement p)
Definition: ri.c:2195
bool control_consistent_p(control p)
Definition: ri.c:496
int occurences_in_control_list(control c, list cs)
Count the number of occurences of a control node in a list of control nodes.
Definition: control.c:319
#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
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#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
bool statement_test_p(statement)
Definition: statement.c:343
#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
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
#define false
Definition: newgen_types.h:80
#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 control_statement(x)
Definition: ri.h:941
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
#define ifdebug(n)
Definition: sg.c:47
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References CONTROL, control_consistent_p(), CONTROL_MAP, control_predecessors, control_statement, control_successors, fprintf(), gen_free_list(), ifdebug, MAP, NIL, occurences_in_control_list(), pips_assert, pips_debug, set_add_element(), set_belong_p(), set_free(), set_make(), set_pointer, statement_consistent_p(), and statement_test_p().

Referenced by control_graph(), controlize(), controlize_forloop(), controlize_goto(), controlize_list(), controlize_list_1(), controlize_sequence(), controlize_statement(), controlize_test(), controlize_whileloop(), find_exit_control_node(), find_or_create_exit_control_node(), get_label_control(), hierarchize_control_list(), and simplified_unstructured().

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

◆ control_list_patch()

void control_list_patch ( list  l,
control  c_old,
control  c_new 
)

Replace in a list of control nodes all the instance of a control node by another one.

Parameters
lis the list of control nodes
c_oldis the control node to remove
c_newis the control node to put instead
Parameters
c_old_old
c_new_new

Definition at line 336 of file control.c.

339 {
340  gen_list_patch(l, (gen_chunk *) c_old, (gen_chunk *) c_new);
341 }
void gen_list_patch(list l, const void *x, const void *y)
Replace all the reference to x in list l by a reference to y:
Definition: list.c:985
A gen_chunk is used to store every object.
Definition: genC.h:58

References gen_list_patch().

Referenced by hierarchize_control_list(), transfer_control_predecessor(), and transfer_control_successor().

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

◆ discard_a_control_sequence_without_its_statements()

void discard_a_control_sequence_without_its_statements ( control  begin,
control  end 
)

Remove a control sequence without touching its statements.

It also removes the reference to the sequence from the predecessors or the successors.

Parameters
beginis the control node we start from
endis the control node to stop at

Of course, there should be a unique path from begin to end.

Unlink any extern reference to the control sequence:

To pass through the free:

Parameters
beginegin
endnd

Definition at line 1111 of file control.c.

1113 {
1114  control c;
1115  list successor_list;
1116 
1117  /* Unlink any extern reference to the control sequence: */
1118  MAP(CONTROL, a_predecessor,
1119  {
1120  gen_remove(&control_successors(a_predecessor),
1121  begin);
1122  },
1123  control_predecessors(begin));
1124 
1125  MAP(CONTROL, a_successor,
1126  {
1127  gen_remove(&control_predecessors(a_successor) ,
1128  end);
1129  },
1131 
1132  for(c = begin; ; c = CONTROL(CAR(successor_list))) {
1133  /* To pass through the free: */
1134  successor_list = control_successors(c);
1135 
1136  pips_assert("discard_a_control_sequence_without_its_statements: not a sequence.", gen_length(successor_list) <= 1);
1137 
1139 
1140  if (c == end)
1141  break;
1142  }
1143 }
void free_a_control_without_its_statement(control c)
Remove a control node without touching its statement, its predecessors and successors,...
Definition: control.c:1087
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
size_t gen_length(const list l)
Definition: list.c:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
char end
Definition: gtk_status.c:82

References CAR, CONTROL, control_predecessors, control_successors, end, free_a_control_without_its_statement(), gen_length(), gen_remove(), MAP, and pips_assert.

Referenced by __attribute__(), restructure_this_test(), and take_out_the_entry_node_of_the_unstructured().

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

◆ discard_an_unstructured_without_its_statements()

void discard_an_unstructured_without_its_statements ( unstructured  u)

Used to discard an unstructured without touching its statements.

The statements are assumed to be referenced in another way.

Parameters
heunstructured to free

Protect the statements by unlinking them:

And then free the discard the unstructured:

Definition at line 1063 of file control.c.

1064 {
1065  list blocs = NIL;
1066 
1067  /* Protect the statements by unlinking them: */
1068  CONTROL_MAP(c,
1069  {
1071  },
1073  blocs);
1074  gen_free_list(blocs);
1075 
1076  /* And then free the discard the unstructured: */
1077  free_unstructured(u);
1078 }
void free_unstructured(unstructured p)
Definition: ri.c:2745
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define statement_undefined
Definition: ri.h:2419

References CONTROL_MAP, control_statement, free_unstructured(), gen_free_list(), NIL, statement_undefined, and unstructured_control.

Referenced by __attribute__().

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

◆ display_address_of_control_nodes()

void display_address_of_control_nodes ( list  cs)

Display the adresses a list of control nodes.

Parameters
csis the control node list
Parameters
css

Definition at line 612 of file control.c.

613 {
614  MAP(CONTROL, cc,
615  {
616  fprintf(stderr, "%p,", cc);
617  }, cs);
618 }

References CONTROL, fprintf(), and MAP.

Referenced by compact_list(), display_interval_graph(), display_linked_control_nodes(), hierarchize_control_list(), and interval_exit_nodes().

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

◆ display_linked_control_nodes()

void display_linked_control_nodes ( control  c)

Display all the control nodes reached or reachable from c for debugging purpose.

Display also the statement of each control node if the debug level is high enough

Parameters
cis the control node we start the visit from

safe_print_statement(control_statement(ctl));

Definition at line 629 of file control.c.

630 {
631  list blocs = NIL;
632  set stmts = set_make(set_pointer);
633 
634  CONTROL_MAP(ctl, {
635  fprintf(stderr, "%p (pred (#%zd)=", ctl,
638  fprintf(stderr, " succ (#%zd)=", gen_length(control_successors(ctl)));
640  fprintf(stderr, "), ");
641  ifdebug(8) {
642  fprintf(stderr, "\n");
643  pips_debug(8, "Statement %p of control %p:\n", control_statement(ctl), ctl);
644  // FI: no cycle with prettyprint
645  /* safe_print_statement(control_statement(ctl)); */
646  }
647  if(set_belong_p(stmts, control_statement(ctl))) {
648  fprintf(stderr, "Statement %p is pointed by two different control nodes\n",
649  control_statement(ctl));
650  }
651  else
652  stmts = set_add_element(stmts, stmts, (void *) control_statement(ctl));
653  }, c, blocs);
654  gen_free_list(blocs);
655  set_free(stmts);
656 
657  fprintf(stderr, "---\n");
658 }
void display_address_of_control_nodes(list cs)
Display the adresses a list of control nodes.
Definition: control.c:612

References CONTROL_MAP, control_predecessors, control_statement, control_successors, display_address_of_control_nodes(), fprintf(), gen_free_list(), gen_length(), ifdebug, NIL, pips_debug, set_add_element(), set_belong_p(), set_free(), set_make(), and set_pointer.

Referenced by clean_up_control(), control_graph(), control_graph_recursive_decomposition(), controlize(), controlize_goto(), controlize_list(), controlize_list_1(), controlize_sequence(), controlize_statement(), controlize_test(), hierarchize_control_list(), recover_structured_while(), remove_all_unreachable_controls_of_an_unstructured(), remove_some_unreachable_controls_of_an_unstructured(), remove_unreachable_following_control(), simplified_unstructured(), unstructured_consistency_p(), and unstructured_while_p().

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

◆ free_a_control_without_its_statement()

void free_a_control_without_its_statement ( control  c)

Remove a control node without touching its statement, its predecessors and successors, if any.

Parameters
cis the control node to free

Protect the statement:

Definition at line 1087 of file control.c.

1087  {
1088  /* Protect the statement: */
1091  control_successors(c) = NIL;
1094 
1095  free_control(c);
1096 }
void free_control(control p)
Definition: ri.c:490

References control_predecessors, control_statement, control_successors, free_control(), gen_free_list(), NIL, and statement_undefined.

Referenced by controlize_test(), discard_a_control_sequence_without_its_statements(), and hcfg().

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

◆ fuse_2_control_nodes()

void fuse_2_control_nodes ( control  first,
control  second 
)

Fuse a 2 control nodes.

It adds the statement of the second one to the statement of the first one. Assumes that the second node is the only successor of the first one.

The second control node is freed.

It does not update the entry or exit field of the unstructured.

Parameters
firstis the first control node
secondis the control node to fuse in the first one. It is precised because it is possible that there are not connected.

If the second node has 2 successors, it is a test node. The fused node has 2 successors and must be a test too. So, the only thing I can do is to remove the first statement, just keeping its comments. And how about the label? It might be useful for syntactic reasons and only reachable via END=nnn after prettyprinting (see Validation/redlec2.f)

A return might be OK?!? What does the caller expect? The first label must be useless and is dropped.

pips_user_warning("Useless label %s\n", entity_name(first_label));

pips_internal_error("Two labels for one control node");

If not, build a block with the two statements:

Reconnect the new statement to the node to fuse:

Unlink the second node from the first one:

Link the first node with the successors of the second one in the forward direction:

Update all the predecessors of the successors:

Transfer the predecessors of the second node to the first one. Note that the original second -> first predecessor link has already been removed. But a loop from second to second appear at this point as a link from first to second. Nasty bug...

Now we remove the useless intermediate node "second":

Do not gen_free_list(control_successors(second)) since it is used as control_successors(first) now:

Parameters
firstirst
secondecond

Definition at line 1391 of file control.c.

1393 {
1394  if (gen_length(control_successors(second)) == 2) {
1395  /* If the second node has 2 successors, it is a test node. The
1396  fused node has 2 successors and must be a test too. So, the
1397  only thing I can do is to remove the first statement, just
1398  keeping its comments. And how about the label? It might be
1399  useful for syntactic reasons and only reachable via END=nnn
1400  after prettyprinting (see Validation/redlec2.f) */
1401  string first_comment =
1403  entity first_label = statement_to_label(control_statement(first));
1404 
1405  if(!entity_empty_label_p(first_label)) {
1406  entity second_label = statement_to_label(control_statement(second));
1407  pips_user_warning("Useless label %s\n",
1408  entity_name(first_label));
1409  if(!entity_empty_label_p(second_label)) {
1410  /* A return might be OK?!? What does the caller expect? The
1411  first label must be useless and is dropped. */
1412  /* pips_user_warning("Useless label %s\n",
1413  entity_name(first_label)); */
1414  /* pips_internal_error("Two labels for one control node"); */
1415  ;
1416  }
1417  else {
1418  statement_label(control_statement(second)) = first_label;
1419  ;
1420  }
1421  }
1423  first_comment);
1424  control_statement(first) = control_statement(second);
1425  }
1426  else {
1427  /* If not, build a block with the two statements: */
1429  statement_instruction(st) =
1431  control_statement(first),
1432  CONS(STATEMENT,
1433  control_statement(second), NIL)));
1434  /* Reconnect the new statement to the node to fuse: */
1435  control_statement(first) = st;
1436  }
1438 
1439  /* Unlink the second node from the first one: */
1441  gen_remove(&control_predecessors(second), first);
1442 
1443  /* Link the first node with the successors of the second one in
1444  the forward direction: */
1445  control_successors(first) =
1446  control_successors(second);
1447  /* Update all the predecessors of the successors: */
1448  MAP(CONTROL, c,
1449  {
1450  MAPL(cp,
1451  {
1452  if (CONTROL(CAR(cp)) == second)
1453  CONTROL_(CAR(cp)) = first;
1454  }, control_predecessors(c));
1455  }, control_successors(first));
1456 
1457  /* Transfer the predecessors of the second node to the first one.
1458  Note that the original second -> first predecessor link has
1459  already been removed. But a loop from second to second appear
1460  at this point as a link from first to second. Nasty bug... */
1461  MAP(CONTROL, c,
1462  {
1464  c,
1465  control_predecessors(first));
1466  MAPL(cp,
1467  {
1468  if (CONTROL(CAR(cp)) == second) {
1469  CONTROL_(CAR(cp)) = first;
1470  }
1471  }, control_successors(c));
1472  }, control_predecessors(second));
1473 
1474  /* Now we remove the useless intermediate node "second": */
1475  /* Do not gen_free_list(control_successors(second)) since it is
1476  used as control_successors(first) now: */
1477  control_successors(second) = NIL;
1479  control_predecessors(second) = NIL;
1480  free_control(second);
1481 }
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#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
entity statement_to_label(statement)
See if statement s is labelled and can be reached by a GO TO.
Definition: statement.c:2090
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
string gather_all_comments_of_a_statement(statement)
Gather all the comments recursively found in the given statement and return them in a strduped string...
Definition: statement.c:1760
#define pips_user_warning
Definition: misc-local.h:146
#define make_empty_statement
An alias for make_empty_block_statement.
bool entity_empty_label_p(entity e)
Definition: entity.c:666
#define CONTROL_(x)
Definition: ri.h:913
#define statement_label(x)
Definition: ri.h:2450
#define entity_name(x)
Definition: ri.h:2790
#define statement_instruction(x)
Definition: ri.h:2458
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87

References CAR, CONS, CONTROL, CONTROL_, control_predecessors, control_statement, control_successors, cp, entity_empty_label_p(), entity_name, free_control(), gather_all_comments_of_a_statement(), gen_free_list(), gen_length(), gen_remove(), insert_comments_to_statement(), make_empty_statement, make_instruction_block(), MAP, MAPL, NIL, pips_user_warning, STATEMENT, statement_instruction, statement_label, statement_to_label(), and statement_undefined.

Referenced by fuse_sequences_in_unstructured().

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

◆ generate_a_statement_list_from_a_control_sequence()

list generate_a_statement_list_from_a_control_sequence ( control  begin,
control  end 
)

Take a control sequence and return a list of all the statements in the sequence (in the same order...

:-) ).

Parameters
beginis the control node we start from
endis the control node to stop at

Of course, there should be a unique path from begin to end.

Because of the way CONS is working, reversed the walk through the sequence.

Add the statement to the list:

Parameters
beginegin
endnd

Definition at line 1156 of file control.c.

1158 {
1159  control c;
1160  list the_statements_of_the_sequence = NIL;
1161 
1162  /* Because of the way CONS is working, reversed the walk through
1163  the sequence. */
1164 
1165  for(c = end; ; c = CONTROL(CAR(control_predecessors(c)))) {
1166  int number_of_predecessor = gen_length(control_predecessors(c));
1167  pips_assert("discard_a_control_sequence_without_its_statements: not a sequence.", number_of_predecessor <= 1);
1168 
1169  /* Add the statement to the list: */
1170  the_statements_of_the_sequence = CONS(STATEMENT,
1171  control_statement(c),
1172  the_statements_of_the_sequence);
1173  if (c == begin)
1174  break;
1175  }
1176 
1177  return the_statements_of_the_sequence;
1178 }

References CAR, CONS, CONTROL, control_predecessors, control_statement, end, gen_length(), NIL, pips_assert, and STATEMENT.

Referenced by __attribute__().

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

◆ insert_control_in_arc()

void insert_control_in_arc ( control  c,
control  before,
control  after 
)

Insert a control node between 2 connected control nodes.

Parameters
cis the control node to insert
beforeis the control node before where c is to be inserted
afteris the control node after where c is to be inserted

Assume that c is not already connected and that after is the successor of before.

Note: statements associated to nodes are not tested in case they are undefined.

If there is no ambiguity about the linking, use Ronan's technique

Let's try to preserve the true and false branch

Parameters
beforeefore
afterfter

Definition at line 1299 of file control.c.

1299  {
1300  // These first two assertions are wrong when "before" is a test whose two
1301  // branches reach "after":
1302  //
1303  // if(c) goto l1; else goto l1; l1: ;
1304  //
1305  // This is unlikely but does happen when macros are used or when
1306  // some code is generated automatically. FI assumes that the two
1307  // substitutions will happen simultaneously thanks to the
1308  // substitutions in the list
1309  pips_assert("c is not already a successor of before",
1311 
1312  // This may be wrong if c has already been inserted in another
1313  //arc. Nevertheless it may be useful to insert it in the "before->after" arc.
1314  //
1315  //pips_assert("c is not a predecessor of after",
1316  // !is_control_in_list_p(c, control_predecessors(after)));
1317 
1318  // Make sure that before and after are properly linked
1319  pips_assert("after is a successor of before",
1320  is_control_in_list_p(after, control_successors(before)));
1321  pips_assert("before is a predecessor of after",
1322  is_control_in_list_p(before, control_predecessors(after)));
1323 
1324  // FI: we might also assert that the statement associated to c is
1325  // not a test... but it is not possible when sequences are
1326  // transformed into a chain of nodes. So, temporarily, you can have
1327  // test control nodes with only one successor. May be definitely if
1328  // they are structured?
1329  //pips_assert("c is not a test: it has only one successor at most",
1330  // !statement_test_p(control_statement(c)));
1331 
1332  // FI: when before is a test, how do you know if c must be in the
1333  // true or in the false branch?
1334  /* If there is no ambiguity about the linking, use Ronan's technique */
1335  if(gen_length(control_successors(before))==1
1336  && gen_length(control_successors(c))==0) {
1337  unlink_2_control_nodes(before, after);
1338  link_2_control_nodes(before, c);
1339  link_2_control_nodes(c, after);
1340  }
1341  else if(gen_length(control_successors(c))==0) {
1342  /* Let's try to preserve the true and false branch */
1343  bool success1 = gen_replace_in_list(control_successors(before), after, c);
1344  bool success2 = gen_replace_in_list(control_predecessors(after), before, c);
1345  // The order is meaning less, but it is easier to debug if the
1346  // order is preserved
1348  = gen_nconc(control_predecessors(c), CONS(CONTROL, before, NIL));
1349  //control_predecessors(c) = CONS(CONTROL, before, NIL);
1350  control_successors(c) = CONS(CONTROL, after, NIL);
1351 
1352  pips_assert("after and before were linked", success1 && success2);
1353  pips_debug(8, "control %p inserted between before=%p and after=%p\n",
1354  c, before, after);
1355  }
1356  else if(gen_length(control_successors(c))==1
1357  && CONTROL(CAR(control_successors(c)))==after) {
1358  // We may handle the case outlined above?
1359  // The two substitutions should have occured simultaneously?
1360  // No, simply the more general case:
1361  // precondition: x -> c && c -> after && before -> after
1362  // postcondition x -> c && before -> c && c -> after
1363  // pips_internal_error("Should not happen\n");
1364  // Preserve the branch positions for tests
1365  bool success = gen_replace_in_list(control_successors(before), after, c);
1366  gen_remove(&control_predecessors(after), before);
1368  = gen_nconc(control_predecessors(c), CONS(CONTROL, before, NIL));
1369  pips_assert("after and before were linked", success);
1370  }
1371  else
1372  pips_internal_error("No semantics, no implementation...\n");
1373 }
bool success
Definition: gpips-local.h:59
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
bool is_control_in_list_p(control c, list cs)
Test if a control node is in a list of control nodes.
Definition: control.c:299
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
bool gen_replace_in_list(list l, const void *s, const void *t)
substitute all item s by t in list l
Definition: list.c:634
#define pips_internal_error
Definition: misc-local.h:149

References CAR, CONS, CONTROL, control_predecessors, control_successors, gen_length(), gen_nconc(), gen_remove(), gen_replace_in_list(), is_control_in_list_p(), link_2_control_nodes(), NIL, pips_assert, pips_debug, pips_internal_error, and unlink_2_control_nodes().

Referenced by controlize_forloop(), controlize_loop(), and find_exit_control_node().

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

◆ is_control_in_list_p()

bool is_control_in_list_p ( control  c,
list  cs 
)

Test if a control node is in a list of control nodes.

FI: is this different from gen_in_list_p(), but for the c type and the qualifiers?

Parameters
ccontrol node to look for
csis the list of control to search through
Returns
true if the control node is in the list
Parameters
css

Definition at line 299 of file control.c.

301 {
302  MAP(CONTROL, cc, {
303  if (cc == c)
304  return true;
305  }, cs);
306  return false;
307 }

References CONTROL, and MAP.

Referenced by insert_control_in_arc(), and wide_forward_control_map_get_blocs().

+ Here is the caller graph for this function:

◆ link_2_control_nodes()

void link_2_control_nodes ( control  source,
control  target 
)

Add an edge between 2 control nodes.

Assume that this edge does not already exist or the source should be an unstructured IF. FI: I am still puzzled how this can work when tests are involved since the semantics of the first and second successor is not paid attention at at all.

Parameters
sourceis the control node the edge starts from
targetis the control node the edge ends to
Parameters
sourceource
targetarget

Definition at line 1193 of file control.c.

1195 {
1196  // FI: should we check here that the statement of "source" is
1197  // defined and if it is defined and that it already has a successor
1198  // then it is a test? Might be better done here than later when
1199  // trying to print out the statements...
1200  // FI: I think this explains why for loops are improperly desugared...
1201 
1202  // FI: this assert is too strong because if statements are
1203  // considered potentially structured and are linked like any other
1204  // statement when processing a statement
1205  //
1206  // pips_assert("source is not a test\n",
1207  // statement_undefined_p(control_statement(source))
1208  // || !statement_test_p(control_statement(source)));
1209 
1210  // FI: to avoid memory leaks and/or inconsistency
1211  //pips_assert("source has no successor\n", ENDP(control_successors(source)));
1212 
1213 #if 0
1214  if(!ENDP(control_successors(source)))
1215  // FI: this should never happen if the graph is properly
1216  // handled...
1217  // I could re-instate the assert and/or just set a breakpoint on
1218  // the gen_free_list()
1220  control_successors(source) = CONS(CONTROL, target, NIL);
1221 #endif
1222 
1223  // FI: assume the callers knows what it is doing when dealing with tests...
1224  control_successors(source) = CONS(CONTROL,
1225  target,
1226  control_successors(source));
1227 
1228  // FI: guess to get for loop properly desugared... but it breaks
1229  // something else...
1230  //control_successors(source) =
1231  // gen_nconc(control_successors(source), CONS(CONTROL, target, NIL));
1232  control_predecessors(target) = CONS(CONTROL,
1233  source,
1234  control_predecessors(target));
1235 }
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66

References CONS, CONTROL, control_predecessors, control_successors, ENDP, gen_free_list(), and NIL.

Referenced by connect_unstructured(), controlize(), controlize_forloop(), controlize_goto(), controlize_list(), controlize_loop(), controlize_repeatloop(), controlize_sequence(), controlize_test(), controlize_whileloop(), full_spaghettify_module(), full_spaghettify_statement(), hcfg(), hierarchize_control_list(), insert_control_in_arc(), make_unstructured_from_forloop(), make_unstructured_from_loop(), make_unstructured_from_test(), move_declaration_control_node_declarations_to_statement(), recover_structured_while(), reduce_sequence(), replace_control_with_unstructured(), and restructure_this_test().

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

◆ link_3_control_nodes()

void link_3_control_nodes ( control  c_test,
control  c_then,
control  c_else 
)

Add an edge between 2 control nodes.

Assume that this edge does not already exist or the source should be an unstructured IF. FI: I am still puzzled how this can work when tests are involved since the semantics of the first and second successor is not paid attention at at all.

Parameters
sourceis the control node the edge starts from
targetis the control node the edge ends to
Parameters
c_test_test
c_then_then
c_else_else

Definition at line 1249 of file control.c.

1251 {
1255  CONS(CONTROL, c_then, CONS(CONTROL, c_else, NIL));
1256 
1257  control_predecessors(c_then) = CONS(CONTROL,
1258  c_test,
1259  control_predecessors(c_then));
1260  control_predecessors(c_else) = CONS(CONTROL,
1261  c_test,
1262  control_predecessors(c_else));
1263 }
static string c_test(test t, bool breakable)

References c_test(), CONS, CONTROL, control_predecessors, control_successors, ENDP, gen_free_list(), and NIL.

Referenced by controlize_repeatloop(), controlize_test(), controlize_whileloop(), make_unstructured_from_test(), and make_unstructured_from_whileloop().

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

◆ occurences_in_control_list()

int occurences_in_control_list ( control  c,
list  cs 
)

Count the number of occurences of a control node in a list of control nodes.

Parameters
ccontrol node to look for
csis the list of control to count through
Returns
the number of occurences
Parameters
css

Definition at line 319 of file control.c.

321 {
322  return gen_occurences((gen_chunk *) c, cs);
323 }
int gen_occurences(const void *vo, const list l)
count occurences of vo in l
Definition: list.c:746

References gen_occurences().

Referenced by check_control_coherency().

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

◆ print_control_node()

void print_control_node ( control  c)

Definition at line 566 of file control.c.

567 {
568  fprintf(stderr,
569  "ctr %p, %zd preds, %zd succs: %s",
570  c,
574  fprintf(stderr,"\tsuccessors:\n");
575  MAP(CONTROL, s, {
576  fprintf(stderr, "\t\t%p %s", s,
578  }, control_successors(c));
579  fprintf(stderr,"\tpredecessors:\n");
580  MAP(CONTROL, p, {
581  fprintf(stderr, "\t\t%p %s", p,
583  }, control_predecessors(c));
584  fprintf(stderr, "\n");
585 }
string safe_statement_identification(statement)
Definition: statement.c:1726

References CONTROL, control_predecessors, control_statement, control_successors, fprintf(), gen_length(), MAP, and safe_statement_identification().

+ Here is the call graph for this function:

◆ print_control_nodes()

void print_control_nodes ( list  l)

Display identification of a list of control nodes.

Definition at line 589 of file control.c.

590 {
591  if(ENDP(l)) {
592  fprintf(stderr, "empty control list");
593  }
594  else {
595  MAP(CONTROL, c, {
596  fprintf(stderr, "%p, %s", c,
598  // The version used in control/bourdoncle.c also had this check
599  // (void) check_control_statement(c);
600  }, l);
601  }
602  fprintf(stderr, "\n");
603 }

References CONTROL, control_statement, ENDP, fprintf(), MAP, and safe_statement_identification().

Referenced by ancestor_map_consistent_p(), bourdoncle_component(), bourdoncle_partition(), controlize_sequence(), node_to_linked_nodes(), scc_to_dag(), and update_partition().

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

◆ remove_a_control_from_a_list_and_relink()

void remove_a_control_from_a_list_and_relink ( control  c,
list  a_source_control_list_of_c,
list  a_dest_control_list_of_c,
remove_a_control_from_a_list_and_relink_direction  which_way 
)

Replace each occurence of c in a_source_control_list_of_c with a a_dest_control_list_of_c:

Parameters
cis the control node to unlink. It is not freed
a_source_control_list_of_cis the list of control nodes to be linked to the a_dest_control_list_of_c list of control nodes
a_dest_control_list_of_cis the list of control nodes to be linked from the a_source_control_list_of_c list of control nodes
which_wayprecise if we deal with successors or predecessors:
  • if it is source_is_predecessor_and_dest_is_successor: a_source_control_list_of_c is considered as predecessors of c and a_dest_control_list_of_c is considered as successors of c

-if it is source_is_successor_and_dest_is_predecessor: a_source_control_list_of_c is considered as successors of c and a_dest_control_list_of_c is considered as predecessors of c

Now, find the corresponding dest in the source list with the same value as c:

Find the reference to c in the the_dest_of_a_source_list:

l is local to the MAPL...

And add the a_dest_control_list_of_c instead of c:

First concatenate (with copy) a_dest_control_list_of_c before what follow c in the list:

Then place this list instead of c in the_dest_of_a_source_list:

Modify the begin of the list:

Deallocate the cons that point to c:

c is now in the memory nowhere:

Parameters
a_source_control_list_of_c_source_control_list_of_c
a_dest_control_list_of_c_dest_control_list_of_c
which_wayhich_way

Definition at line 913 of file control.c.

917 {
918  MAPL(a_control_list,
919  {
920  list *the_dest_of_a_source_list = NULL;
921  list the_position_of_c = NIL;
922  list the_position_before_c = NIL;
923  list l = NIL;
924 
925  control a_dest_of_a_source = CONTROL(CAR(a_control_list));
926  /* Now, find the corresponding dest in the source list
927  with the same value as c: */
928  switch(which_way) {
930  the_dest_of_a_source_list = &control_successors(a_dest_of_a_source);
931  break;
933  the_dest_of_a_source_list = &control_predecessors(a_dest_of_a_source);
934  break;
935  default:
936  pips_assert("remove_a_control_from_a_list_and_relink with not a good \"which_way\".\n", false);
937  }
938 
939  /* Find the reference to c in the the_dest_of_a_source_list: */
940  the_position_before_c = NIL;
941  MAPL(a_list,
942  {
943  /* l is local to the MAPL... */
944  if (CONTROL(CAR(the_position_of_c = a_list)) == c)
945  break;
946  the_position_before_c = the_position_of_c;
947  },
948  *the_dest_of_a_source_list);
949 
950  /* And add the a_dest_control_list_of_c instead of c: */
951  /* First concatenate (with copy) a_dest_control_list_of_c
952  before what follow c in the list: */
953  l = gen_append(a_dest_control_list_of_c, CDR(the_position_of_c));
954 
955  /* Then place this list instead of c in
956  *the_dest_of_a_source_list: */
957  if (the_position_before_c == NIL)
958  /* Modify the begin of the list: */
959  *the_dest_of_a_source_list = l;
960  else
961  CDR(the_position_before_c) = l;
962 
963  /* Deallocate the cons that point to c: */
964  CDR(the_position_of_c) = NIL;
965  gen_free_list(the_position_of_c);
966  },
967  a_source_control_list_of_c);
968 
969  /* c is now in the memory nowhere: */
971  control_successors(c) = NIL;
972 }
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_append(list l1, const list l2)
Definition: list.c:471
@ source_is_predecessor_and_dest_is_successor
Put some strange number to avoid random clash as much as possible...
@ source_is_successor_and_dest_is_predecessor

References CAR, CDR, CONTROL, control_predecessors, control_successors, gen_append(), gen_free_list(), MAPL, NIL, pips_assert, source_is_predecessor_and_dest_is_successor, and source_is_successor_and_dest_is_predecessor.

Referenced by remove_a_control_from_an_unstructured().

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

◆ remove_a_control_from_an_unstructured()

void remove_a_control_from_an_unstructured ( control  c)

Remove a control node from a control graph.

The control node is freed and its predecessors are relinked to its successor and relink the successor and the predecessor.

If you want to preserve the control statement, do a control_statement(c) = statement_undefined before calling this function.

Parameters
[in,out]cis the control node to unlink and to free

Assume that it cannot have more than 1 successor (so no test node)

If the graph is in an unstructured and c is either the entry or exit node, do not forget to update the entry or exit node.

Unlink from the predecessor. Note that a node may have more than one predecessor. Since we cannot discard an IF this way, we have at most 1 successor:

Unlink from the successor:

Remove the control node:

Definition at line 992 of file control.c.

993 {
994  list the_predecessors = control_predecessors(c);
995  list the_successors = control_successors(c);
996 
997  int number_of_successors = gen_length(the_successors);
998 
999  /* Unlink from the predecessor. Note that a node may have more than
1000  one predecessor. Since we cannot discard an IF this way, we have
1001  at most 1 successor: */
1002  pips_assert("remove_a_control_from_an_unstructured:"
1003  " no more than one successor",
1004  number_of_successors <= 1);
1006  the_predecessors,
1007  the_successors,
1009 
1010  /* Unlink from the successor: */
1012  the_successors,
1013  the_predecessors,
1015 
1016  /* Remove the control node: */
1017  free_control(c);
1018 }
void remove_a_control_from_a_list_and_relink(control c, list a_source_control_list_of_c, list a_dest_control_list_of_c, remove_a_control_from_a_list_and_relink_direction which_way)
Replace each occurence of c in a_source_control_list_of_c with a a_dest_control_list_of_c:
Definition: control.c:913

References control_predecessors, control_successors, free_control(), gen_length(), pips_assert, remove_a_control_from_a_list_and_relink(), source_is_predecessor_and_dest_is_successor, and source_is_successor_and_dest_is_predecessor.

Referenced by compact_list(), controlize_forloop(), controlize_loop(), controlize_repeatloop(), controlize_sequence(), controlize_whileloop(), and remove_useless_continue_or_empty_code_in_unstructured().

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

◆ remove_a_control_from_an_unstructured_without_relinking()

void remove_a_control_from_an_unstructured_without_relinking ( control  c)

It removes a control node from its successor and predecessor.

It can be applied to an unstructured "IF".

Parameters
cis the control node to unlink and to free

If the graph is in an unstructured and

Parameters
cis either the entry or exit node, do not forget to update the entry or exit node.

Use a copy since we iterate and discard at the same time:

Remove the control node itself:

Definition at line 1031 of file control.c.

1032 {
1033  /* Use a copy since we iterate and discard at the same time: */
1034  list the_predecessors = gen_copy_seq(control_predecessors(c));
1035  list the_successors = gen_copy_seq(control_successors(c));
1036 
1037  MAP(CONTROL, a_predecessor, {
1038  unlink_2_control_nodes(a_predecessor, c);
1039  }, the_predecessors);
1040  gen_free_list(the_predecessors);
1041 
1042  MAP(CONTROL, a_successor, {
1043  unlink_2_control_nodes(c, a_successor);
1044  }, the_successors);
1045  gen_free_list(the_successors);
1046 
1047  pips_assert("The control node should not have any connection here,",
1049  /* Remove the control node itself: */
1050  free_control(c);
1051 }
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501

References CONTROL, control_predecessors, control_successors, free_control(), gen_copy_seq(), gen_free_list(), MAP, NIL, pips_assert, and unlink_2_control_nodes().

Referenced by controlize_sequence(), controlize_test(), recover_structured_while(), and remove_all_unreachable_controls_of_an_unstructured().

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

◆ remove_all_unreachable_controls_of_an_unstructured()

void remove_all_unreachable_controls_of_an_unstructured ( unstructured  u)

Remove all control nodes that are not forward reachable from the entry node.

Warning: useful FORMAT that are unreachable are also discarded, so...

Parameters
uis the unstructured to clean

The entry point of the unstructured:

Mark all the forward-reachable nodes:

Now build the remove list from all the non-marked nodes:

The same thing from the exit node that may be not reachable from the entry node:

And delete them:

Definition at line 812 of file control.c.

813 {
814  list blocs = NIL;
815 
816  set useful_controls = set_make(set_pointer);
817  set unreachable_controls = set_make(set_pointer);
818 
819  /* The entry point of the unstructured: */
820  control entry_node = unstructured_control(u);
821  control exit_node = unstructured_exit(u);
822  pips_debug(7, "From control %p, exit %p.\n", entry_node, exit_node);
823  ifdebug(7) {
824  display_linked_control_nodes(entry_node);
825  }
826 
827  /* Mark all the forward-reachable nodes: */
829  pips_debug(5, "Forward visiting control node %p.\n", c);
830  set_add_element(useful_controls,
831  useful_controls,
832  (char *) c);
833  },
834  entry_node,
835  blocs);
836  gen_free_list(blocs);
837  blocs = NIL;
838 
839  /* Now build the remove list from all the non-marked nodes: */
840  CONTROL_MAP(c, {
841  pips_debug(5, "Testing control node %p.\n", c);
842  if (! set_belong_p(useful_controls, (char *) c)) {
843  pips_debug(5, "Adding to the removing list control node %p.\n", c);
844  set_add_element(unreachable_controls,
845  unreachable_controls,
846  (char *) c);
847  }
848  },
849  entry_node,
850  blocs);
851  gen_free_list(blocs);
852  blocs = NIL;
853 
854  /* The same thing from the exit node that may be not reachable
855  from the entry node: */
856  CONTROL_MAP(c, {
857  pips_debug(5, "Testing from exit control node %p.\n", c);
858  if (! set_belong_p(useful_controls, (char *) c)) {
859  pips_debug(5, "From exit node: Adding to the removing list control node %p.\n", c);
860  set_add_element(unreachable_controls,
861  unreachable_controls,
862  (char *) c);
863  }
864  },
865  exit_node,
866  blocs);
867  gen_free_list(blocs);
868 
869  /* And delete them: */
870  SET_MAP(cc, {
871  control c = (control) cc;
872  if (c == exit_node) {
873  pips_debug(5, "Skipping discarding exit control node %p.\n", c);
874  }
875  else {
876  pips_debug(5, "Discarding control node %p.\n", c);
878  pips_user_warning("Discarding an unreachable FORMAT that may be "
879  "usefull. "
880  "Try to use the GATHER_FORMATS_AT_BEGINNING "
881  "property.\n");
883  }
884  },
885  unreachable_controls);
886  set_free(useful_controls);
887  set_free(unreachable_controls);
888 }
void display_linked_control_nodes(control c)
Display all the control nodes reached or reachable from c for debugging purpose.
Definition: control.c:629
void remove_a_control_from_an_unstructured_without_relinking(control c)
It removes a control node from its successor and predecessor.
Definition: control.c:1031
#define FORWARD_CONTROL_MAP(ctl, code, c, list)
Walk through all the controls forward-reachable from a given control node of an unstructured.
bool format_inside_statement_p(statement)
Definition: statement.c:2360
struct _newgen_struct_control_ * control
#define SET_MAP(element, code, the_set)
Definition: newgen_set.h:54
#define unstructured_exit(x)
Definition: ri.h:3006

References CONTROL_MAP, control_statement, display_linked_control_nodes(), format_inside_statement_p(), FORWARD_CONTROL_MAP, gen_free_list(), ifdebug, NIL, pips_debug, pips_user_warning, remove_a_control_from_an_unstructured_without_relinking(), set_add_element(), set_belong_p(), set_free(), set_make(), SET_MAP, set_pointer, unstructured_control, and unstructured_exit.

Referenced by clean_up_control().

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

◆ remove_some_unreachable_controls_of_an_unstructured()

void remove_some_unreachable_controls_of_an_unstructured ( unstructured  u)

Remove all the control sequences that are unreachable and that begin with a node without any predecessor.

It is an old version and a normal user should use remove_all_unreachable_controls_of_an_unstructured() instead.

It is still buggy on Validation/Syntax/asgoto.f...

The entry point of the unstructured:

Well, the entry node is guessed as reachable... :-)

A control without predecessor is unreachable, so it is dead code:

Note that we could have entry_node == exit_node...

Now remove all the marqued sequences from the entry_node:

Do not forget the unreachable exit part if it is not connex to the entry_node:

Do not remove the exit_node...

A control without predecessor is unreachable, so it is dead code:

Now remove all the marqued sequences from the entry_node:

Definition at line 730 of file control.c.

731 {
732  list blocs = NIL;
733  list control_remove_list = NIL;
734 
735  /* The entry point of the unstructured: */
736  control entry_node = unstructured_control(u);
737  control exit_node = unstructured_exit(u);
738  bool exit_node_has_been_seen = false;
739  pips_debug(7, "From control %p, exit %p.\n", entry_node, exit_node);
740  ifdebug(7) {
741  display_linked_control_nodes(entry_node);
742  }
743 
744  CONTROL_MAP(c,
745  {
746  if (c != entry_node)
747  /* Well, the entry node is guessed as
748  reachable... :-) */
749  if (control_predecessors(c) == NIL) {
750  /* A control without predecessor is
751  unreachable, so it is dead code: */
752  pips_debug(7, "Want to discard control %p.\n", c);
753  control_remove_list = CONS(CONTROL,
754  c,
755  control_remove_list);
756  }
757  if (c == exit_node)
758  /* Note that we could have entry_node ==
759  exit_node... */
760  exit_node_has_been_seen = true;
761  },
762  entry_node,
763  blocs);
764  gen_free_list(blocs);
765 
766  /* Now remove all the marqued sequences from the entry_node: */
767  MAP(CONTROL, c,
768  {
769  remove_unreachable_following_control(c, entry_node, exit_node);
770  },
771  control_remove_list);
772  gen_free_list(control_remove_list);
773 
774  if (!exit_node_has_been_seen) {
775  /* Do not forget the unreachable exit part if it is not connex
776  to the entry_node: */
777  blocs = NIL;
778  control_remove_list = NIL;
779  CONTROL_MAP(c,
780  {
781  if (c != exit_node)
782  /* Do not remove the exit_node... */
783  if (control_predecessors(c) == NIL) {
784  /* A control without predecessor is
785  unreachable, so it is dead code: */
786  control_remove_list = CONS(CONTROL,
787  c,
788  control_remove_list);
789  }
790  },
791  exit_node,
792  blocs);
793  gen_free_list(blocs);
794  /* Now remove all the marqued sequences from the entry_node: */
795  MAP(CONTROL, c,
796  {
797  remove_unreachable_following_control(c, entry_node, exit_node);
798  },
799  control_remove_list);
800  gen_free_list(control_remove_list);
801  }
802 }
void remove_unreachable_following_control(control c, control do_not_delete_node, control do_not_delete_node_either)
Remove all the control nodes (with their statements) from c in the successor tree of c up to the node...
Definition: control.c:682

References CONS, CONTROL, CONTROL_MAP, control_predecessors, display_linked_control_nodes(), gen_free_list(), ifdebug, MAP, NIL, pips_debug, remove_unreachable_following_control(), unstructured_control, and unstructured_exit.

+ Here is the call graph for this function:

◆ remove_unreachable_following_control()

void remove_unreachable_following_control ( control  c,
control  do_not_delete_node,
control  do_not_delete_node_either 
)

Remove all the control nodes (with their statements) from c in the successor tree of c up to the nodes with more than 1 predecessor, that is when it reach another flow.

The entry node of the unstructured is given to avoid removing it when there is an unreachable sequence pointing on it.

If a control node contains a FORMAT, assume that it is useful and stop removing.

The

Parameters
do_not_delete_nodeis expected to be the entry or the exit node for example in order not to delete them.
cis the control we start the deletion from.
do_not_delete_nodeis a control node we stop at when encountered
do_not_delete_node_eitheris another control node we stop at when encountered

If this is the do_not_delete_node nodes: stop deleting:

If this is not or no more the begin of a sequence, stop deleting:

If there is a FORMAT inside a control node, just stop deleting the control nodes since we cannot decide locally if the FORMAT is useful or not:

Save the successor list since we iterate o it and discard it at the same time:

Ok, we can delete. For each successor of c:

Remove any predecessor reference of itself in this successor:

Discard the control node itself:

Parameters
do_not_delete_nodeo_not_delete_node
do_not_delete_node_eithero_not_delete_node_either

Definition at line 682 of file control.c.

685 {
686  list the_successors;
687 
688  /* If this is the do_not_delete_node nodes: stop deleting: */
689  if (c == do_not_delete_node || c == do_not_delete_node_either)
690  return;
691  /* If this is not or no more the begin of a sequence, stop deleting: */
692  if (control_predecessors(c) != NIL)
693  return;
694  /* If there is a FORMAT inside a control node, just stop deleting
695  the control nodes since we cannot decide locally if the FORMAT
696  is useful or not: */
698  return;
699 
700  /* Save the successor list since we iterate o it and discard it at
701  the same time: */
702  the_successors = gen_copy_seq(control_successors(c));
703  /* Ok, we can delete. For each successor of c: */
704  MAP(CONTROL, a_successor, {
705  /* Remove any predecessor reference of itself in this
706  successor: */
707  unlink_2_control_nodes(c, a_successor);
709  do_not_delete_node,
710  do_not_delete_node_either);
711  }, the_successors);
712  gen_free_list(the_successors);
713 
714  /* Discard the control node itself: */
715  pips_debug(7, "Discarding control node %p.\n", c);
716  ifdebug(7) {
718  }
719  free_control(c);
720 }

References CONTROL, control_predecessors, control_statement, control_successors, display_linked_control_nodes(), format_inside_statement_p(), free_control(), gen_copy_seq(), gen_free_list(), ifdebug, MAP, NIL, pips_debug, and unlink_2_control_nodes().

Referenced by remove_some_unreachable_controls_of_an_unstructured().

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

◆ replace_control_related_to_a_list()

void replace_control_related_to_a_list ( control  old_node,
control  new_node,
list  controls 
)

Replace all the references to a control node by a new one in the successors & predecessors of a list of controls.

Parameters
old_nodeis the control node to replace
new_nodeis the control node to replace
controlsis a list of controls we want to disconnect from old_node and reconnect to new_node instead

Need a intermediate list since we cannot iterate on control_successors(old_node) for example and modifying it...

Since we need to keep successors order (to avoid for example IF/THEN/ELSE transformed in IF/ELSE/THEN), iterate directly on the links of old_node instead of on controls:

First transfer the successors in controls from old_node to new_node:

Use gen_nconc to keep test order:

And then do the modification:

Hmmm... We need to transfer a loop around old_node to a loop around new_node:

Create the new loop around new_node:

Delete the old one. Use gen_remove_once() instead of gen_remove() to deal with double loops around a node (See hierarchy02.f in validation):

And then transfer the predecessors in controls from old_node to new_node (the previous double loops have disappeared here):

Use gen_nconc to keep test order:

And then do the modification:

Parameters
old_nodeld_node
new_nodeew_node
controlsontrols

Definition at line 419 of file control.c.

422 {
423  /* Need a intermediate list since we cannot iterate on
424  control_successors(old_node) for example and modifying it...*/
425  list controls_to_change = NIL;
426  /* Since we need to keep successors order (to avoid for example
427  IF/THEN/ELSE transformed in IF/ELSE/THEN), iterate directly on
428  the links of old_node instead of on controls: */
429  /* First transfer the successors in controls from old_node to
430  new_node: */
431  MAP(CONTROL, c, {
432  if (gen_in_list_p(c, controls))
433  /* Use gen_nconc to keep test order: */
434  controls_to_change = gen_nconc(controls_to_change,
435  CONS(CONTROL, c, NIL));
436  }, control_successors(old_node));
437  /* And then do the modification: */
438  MAP(CONTROL, c, {
439  pips_debug(8, "Transfer old node %p to new node %p in successor %p\n", old_node, new_node, c);
440  if (c != old_node)
441  transfer_control_successor(old_node, new_node, c);
442  else {
443  /* Hmmm... We need to transfer a loop around old_node to a
444  loop around new_node: */
445  /* Create the new loop around new_node: */
446  control_successors(new_node) =
447  gen_nconc(control_successors(new_node),
448  CONS(CONTROL, new_node, NIL));
449  control_predecessors(new_node) =
451  CONS(CONTROL, new_node, NIL));
452  /* Delete the old one. Use gen_remove_once() instead of
453  gen_remove() to deal with double loops around a node
454  (See hierarchy02.f in validation): */
455  gen_remove_once(&control_successors(old_node), (gen_chunk *) old_node);
456  gen_remove_once(&control_predecessors(old_node), (gen_chunk *) old_node);
457  }
458  }, controls_to_change);
459  gen_free_list(controls_to_change);
460 
461  /* And then transfer the predecessors in controls from old_node to
462  new_node (the previous double loops have disappeared here): */
463  controls_to_change = NIL;
464  MAP(CONTROL, c, {
465  if (gen_in_list_p(c, controls))
466  /* Use gen_nconc to keep test order: */
467  controls_to_change = gen_nconc(controls_to_change,
468  CONS(CONTROL, c, NIL));
469  }, control_predecessors(old_node));
470  /* And then do the modification: */
471  MAP(CONTROL, c, {
472  pips_debug(8, "Transfer old node %p to new node %p in predecessor %p\n", old_node, new_node, c);
473  transfer_control_predecessor(old_node, new_node, c);
474  }, controls_to_change);
475  gen_free_list(controls_to_change);
476 }
void transfer_control_successor(control old_node, control new_node, control c)
Transfer a control node as a successor of one node to another one.
Definition: control.c:390
void transfer_control_predecessor(control old_node, control new_node, control c)
Transfer a control node as a predecessor from one node to another one.
Definition: control.c:358
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734

References CONS, CONTROL, control_predecessors, control_successors, gen_free_list(), gen_in_list_p(), gen_nconc(), gen_remove_once(), MAP, NIL, pips_debug, transfer_control_predecessor(), and transfer_control_successor().

+ Here is the call graph for this function:

◆ transfer_control_predecessor()

void transfer_control_predecessor ( control  old_node,
control  new_node,
control  c 
)

Transfer a control node as a predecessor from one node to another one.

It disconnected a node c that was pointing to (was a predecessor of) old_node and reconnect it to new_node that becomes its new successor instead.

Parameters
old_nodethe control node that was a successor of c
new_nodethe control node that will be a successor of c
cthe control node that is disconnected of old_node and connected to new_node

Add c as a predecessor of new_node:

Remove c as a predecessor of old_node:

Correct the reverse link c->old_node to c->new_node:

Parameters
old_nodeld_node
new_nodeew_node

Definition at line 358 of file control.c.

361 {
363  if (predecessor == c)
364  /* Add c as a predecessor of new_node: */
365  control_predecessors(new_node) =
367  CONS(CONTROL, c, NIL));
368  }, control_predecessors(old_node));
369  /* Remove c as a predecessor of old_node: */
370  gen_remove(&control_predecessors(old_node), c);
371  /* Correct the reverse link c->old_node to c->new_node: */
372  control_list_patch(control_successors(c), old_node, new_node);
373 }
void control_list_patch(list l, control c_old, control c_new)
Replace in a list of control nodes all the instance of a control node by another one.
Definition: control.c:336

References CONS, CONTROL, control_list_patch(), control_predecessors, control_successors, gen_nconc(), gen_remove(), MAP, and NIL.

Referenced by replace_control_related_to_a_list().

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

◆ transfer_control_successor()

void transfer_control_successor ( control  old_node,
control  new_node,
control  c 
)

Transfer a control node as a successor of one node to another one.

It disconnected a node c that was coming from (was a successor of) old_node and reconnect it to new_node that becomes its new predecessor instead.

Parameters
old_nodethe control node that was a predecessor of c
new_nodethe control node that will be a predecessor of c
cthe control node that is disconnected of old_node and connected to new_node

Add c as a predecessor of new_node:

Remove c as a successor of old_node:

Correct the reverse link c->old_node to c->new_node:

Parameters
old_nodeld_node
new_nodeew_node

Definition at line 390 of file control.c.

393 {
394  MAP(CONTROL, successor, {
395  if (successor == c)
396  /* Add c as a predecessor of new_node: */
397  control_successors(new_node) =
398  gen_nconc(control_successors(new_node),
399  CONS(CONTROL, c, NIL));
400  }, control_successors(old_node));
401  /* Remove c as a successor of old_node: */
402  gen_remove(&control_successors(old_node), c);
403  /* Correct the reverse link c->old_node to c->new_node: */
404  control_list_patch(control_predecessors(c), old_node, new_node);
405 }

References CONS, CONTROL, control_list_patch(), control_predecessors, control_successors, gen_nconc(), gen_remove(), MAP, and NIL.

Referenced by replace_control_related_to_a_list().

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

◆ unlink_2_control_nodes()

void unlink_2_control_nodes ( control  source,
control  target 
)

Remove all edged between 2 control nodes.

Note: if the source is a test, the false branch may be come the true branch if the true branch is unlinked

Parameters
sourceis the control node the edges start from
targetis the control node the edges end to
Parameters
sourceource
targetarget

Definition at line 1276 of file control.c.

1278 {
1279  // FI: no check that the nodes are properly linked before unlinking
1280  gen_remove(&control_successors(source), target);
1281  gen_remove(&control_predecessors(target), source);
1282 }

References control_predecessors, control_successors, and gen_remove().

Referenced by connect_unstructured(), controlize(), controlize_forloop(), controlize_goto(), controlize_list(), controlize_loop(), controlize_repeatloop(), controlize_sequence(), controlize_test(), controlize_whileloop(), full_spaghettify_statement(), hierarchize_control_list(), insert_control_in_arc(), move_declaration_control_node_declarations_to_statement(), recover_structured_while(), reduce_sequence(), remove_a_control_from_an_unstructured_without_relinking(), remove_unreachable_following_control(), replace_control_with_unstructured(), and restructure_this_test().

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