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

Go to the source code of this file.

Functions

bool unstructured_consistency_p (unstructured u, bool assert_p)
 Basic functions about control flow graphs (CFG), aka unstructured data structure. More...
 
bool unstructured_while_p (unstructured u)
 Test if an unstructured is found to be like a structured while-loop. More...
 

Function Documentation

◆ unstructured_consistency_p()

bool unstructured_consistency_p ( unstructured  u,
bool  assert_p 
)

Basic functions about control flow graphs (CFG), aka unstructured data structure.

cfg.c

Francois Irigoin, 1997. Check some nice properties expected to be true after a powerful enough controlizer phase.

The calls to pips_assert could be replaced by calls to user_warning, the control graph could be printed out before core dumping,...

See also check_control_coherency().

the exit and entry nodes must be different or the unstructured would have been reduced to one structured statement

The entry node must have at least one predecessor: else it should have been moved out of the unstructured. Note that it has in fact TWO predecessors since it is the unstructured entry point.

The exit node should have no successors: its real successor is the statement following the unstructured

The exit node should not be a test: else one of its successors should be control_undefined since it would be outside of the unstructured, or the exit condition would be unknown.

The exit node may have no predecessor because an infinite loop appears in the code. Or it is a successor of the entry node.

RK: ??? If the exit node is unreachable, it should be a CONTINUE Since a CONTINUE has no effects, it does not perturb analyses even if they do not check reachability. RK: The NOP might be the empty sequence instead of a CONTINUE?

If the exit node has only one predecessor, it should be a test or the exit node would have been moved outside of the unstructured.

Since sequences are merged into a unique node, if a node c1 has only one successor c2, and if c2 has only one predecessor c3, c3 must be c1 and either c1 is the exit node which is impossible because there would be no exit condition and the exit node would have a successor, c2, or c2 is the entry node. So c2 must be the entry node.

Well, this is not true because only tests can have two successors. hence, a test node cannot be merged.

Parameters
assert_pssert_p

Definition at line 52 of file cfg.c.

53 {
54  control entry_node = unstructured_control(u);
55  control exit_node = unstructured_exit(u);
56  bool consistency_p = true;
57  list nodes = NIL;
58 
59  forward_control_map_get_blocs(entry_node, &nodes);
60 
61  /* the exit and entry nodes must be different or the
62  * unstructured would have been reduced to one structured statement
63  */
64  if(exit_node==entry_node) {
65  consistency_p = false;
66  if(assert_p) pips_assert("Entry and exit nodes are different", false);
67  }
68 
69  /* The entry node must have at least one predecessor:
70  * else it should have been moved out of the unstructured.
71  * Note that it has in fact TWO predecessors since it is the
72  * unstructured entry point.
73  */
74  if(consistency_p && ENDP(control_predecessors(entry_node))) {
75  consistency_p = false;
76  if(assert_p) pips_assert("Entry node has at least one predecessor", false);
77  }
78 
79  /* The exit node should have no successors: its real successor
80  * is the statement following the unstructured
81  */
82  if(consistency_p && !ENDP(control_successors(exit_node))) {
83  consistency_p = false;
84  if(assert_p) pips_assert("Exit node has no successor", false);
85  }
86 
87  /* The exit node should not be a test:
88  * else one of its successors should be control_undefined
89  * since it would be outside of the unstructured, or the
90  * exit condition would be unknown.
91  */
92  if(consistency_p) {
93  statement exit_s = control_statement(exit_node);
94  if(statement_test_p(exit_s)) {
95  consistency_p = false;
96  if(assert_p) pips_assert("Exit node is not a test", false);
97  }
98  }
99 
100  /* The exit node may have no predecessor because an infinite loop
101  * appears in the code. Or it is a successor of the entry node.
102  */
103  if(consistency_p && !ENDP(control_predecessors(exit_node))) {
104  if(gen_find_eq(exit_node, nodes)!=exit_node) {
105  consistency_p = false;
106  if(assert_p) pips_assert("Exit node has predecessors but is unreachable", false);
107  }
108  }
109 
110  /* RK: ??? If the exit node is unreachable, it should be a CONTINUE
111  * Since a CONTINUE has no effects, it does not perturb analyses even
112  * if they do not check reachability.
113  * RK: The NOP might be the empty sequence instead of a CONTINUE?
114  */
115  if(consistency_p && ENDP(control_predecessors(exit_node))) {
116  statement exit_s = control_statement(exit_node);
117 
118  if(!continue_statement_p(exit_s)) {
119  consistency_p = false;
120  if(assert_p) pips_assert("Unreachable exit node is a CONTINUE statement", false);
121  }
122  }
123 
124  /* If the exit node has only one predecessor, it should
125  * be a test or the exit node would have been moved outside of
126  * the unstructured.
127  */
128  if(consistency_p && gen_length(control_predecessors(exit_node))==1) {
129  control c = CONTROL(CAR(control_predecessors(exit_node)));
131 
132  if(!statement_test_p(s)) {
133  consistency_p = false;
134  if(assert_p) pips_assert("Unique predecessor of exit node is a test", false);
135  }
136  }
137 
138  /* Since sequences are merged into a unique node, if a node c1 has only one
139  * successor c2, and if c2 has only one predecessor c3, c3 must be c1
140  * and either c1 is the exit node which is impossible because there
141  * would be no exit condition and the exit node would have a
142  * successor, c2, or c2 is the entry node. So c2 must be the entry node.
143  *
144  * Well, this is not true because only tests can have two successors.
145  * hence, a test node cannot be merged.
146  */
147  MAP(CONTROL, c1, {
148  if(gen_length(control_successors(c1))==1) {
150  statement s2 = control_statement(c2);
151 
152  if(gen_length(control_predecessors(c2))==1) {
154  if(c1!=c3) {
155  consistency_p = false;
156  if(assert_p) {
157  (void) fprintf(stderr,
158  "\nEntry node: %p\nExit node: %p\n"
159  "c1 node: %p\nc2 node: %p\nc3 node: %p\n",
160  entry_node, exit_node, c1, c2, c3);
161  display_linked_control_nodes(entry_node);
162  pips_assert("c3, the unique predecessor of the unique successor of c1, is c1",
163  false);
164  }
165  }
166  else if(c2!=entry_node && !statement_test_p(s2)) {
167  consistency_p = false;
168  if(assert_p) {
169  (void) fprintf(stderr,
170  "\nEntry node: %p\nExit node: %p\nc1 node: %p\nc2 node: %p\n\n",
171  entry_node, exit_node, c1, c2);
172  display_linked_control_nodes(entry_node);
173  pips_assert("c2 is the unique successor of c1. "
174  "c2 has c1 as unique predecessor. c2 must be the entry node",
175  false);
176  }
177  }
178  }
179 
180  }
181  }, nodes)
182 
183  gen_free_list(nodes);
184 
185  return consistency_p;
186 }
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 forward_control_map_get_blocs(c, l)
Build recursively the list of all controls forward-reachable from a control of an unstructured.
Definition: control.c:208
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
void * gen_find_eq(const void *item, const list seq)
Definition: list.c:422
#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
bool continue_statement_p(statement)
Test if a statement is a CONTINUE, that is the FORTRAN nop, the ";" in C or the "pass" in Python....
Definition: statement.c:203
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#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 control_statement(x)
Definition: ri.h:941
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References CAR, continue_statement_p(), CONTROL, control_predecessors, control_statement, control_successors, display_linked_control_nodes(), ENDP, forward_control_map_get_blocs(), fprintf(), gen_find_eq(), gen_free_list(), gen_length(), MAP, NIL, pips_assert, statement_test_p(), unstructured_control, and unstructured_exit.

Referenced by unstructured_while_p().

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

◆ unstructured_while_p()

bool unstructured_while_p ( unstructured  u)

Test if an unstructured is found to be like a structured while-loop.

Make sure that the unstructured has been "normalized"

while_p = unstructured_consistency_p(u, true);

An unstructured is a while loop if and only if the exit node has only one predecessor and if the entry node is a successor of the predecessor of the exit node.

A loop with two exit conditions is not recognized as a while loop.

A loop with an exit test on entry, a final exit test (do...while) or an exit test anywhere is recognized as a while loop.

Definition at line 191 of file cfg.c.

192 {
193  control entry_node = unstructured_control(u);
194  control exit_node = unstructured_exit(u);
195  bool while_p = false;
196 
197  ifdebug(5) {
198  debug(5, "unstructured_while_p", "Begin with graph\n");
199  (void) fprintf(stderr,
200  "\nEntry node: %p\nExit node: %p\n\n",
201  entry_node, exit_node);
202  display_linked_control_nodes(entry_node);
203  }
204 
205  /* Make sure that the unstructured has been "normalized" */
206  /* while_p = unstructured_consistency_p(u, true); */
207  while_p = unstructured_consistency_p(u, false);
208 
209  /* An unstructured is a while loop if and only if the exit node
210  * has only one predecessor and if the entry node is a successor
211  * of the predecessor of the exit node.
212  *
213  * A loop with two exit conditions is not recognized as a while loop.
214  *
215  * A loop with an exit test on entry, a final exit test (do...while) or
216  * an exit test anywhere is recognized as a while loop.
217  */
218 
219  if(while_p && gen_length(control_predecessors(exit_node))==1) {
220  control pred = CONTROL(CAR(control_predecessors(exit_node)));
221  list succs = NIL;
222 
223  forward_control_map_get_blocs(pred, &succs);
224 
225  if(gen_find_eq(entry_node, succs)==entry_node) {
226  while_p = true;
227  }
228  gen_free_list(succs);
229  }
230  else {
231  while_p = false;
232  }
233 
234  debug(5, "unstructured_while_p", "End with while_p=%s\n", bool_to_string(while_p));
235 
236  return while_p;
237 }
bool unstructured_consistency_p(unstructured u, bool assert_p)
Basic functions about control flow graphs (CFG), aka unstructured data structure.
Definition: cfg.c:52
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
string bool_to_string(bool)
Definition: string.c:243
#define ifdebug(n)
Definition: sg.c:47

References bool_to_string(), CAR, CONTROL, control_predecessors, debug(), display_linked_control_nodes(), forward_control_map_get_blocs(), fprintf(), gen_find_eq(), gen_free_list(), gen_length(), ifdebug, NIL, unstructured_consistency_p(), unstructured_control, and unstructured_exit.

Referenced by instruction_flt(), and instruction_rwt().

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