25 #include "pips_config.h"
30 char vcid_unspaghettify[] =
"%A% ($Date: 2004/01/23 13:55:04 $, ) version $Revision: 14223 $, got on %D%, %T% [%P%].\n Copyright (c) ï¿œcole des Mines de Paris Proprietary.";
47 #include "resources.h"
107 user_log(
"Total number of restructurations: %d\n",
110 if (number_of_restructured_tests != 0) {
111 user_log(
"%d test%s %s been restructured:\n",
112 number_of_restructured_tests,
113 number_of_restructured_tests > 1 ?
"s" :
"",
114 number_of_restructured_tests > 1 ?
"have" :
"has");
115 user_log(
"\t %d IF/THEN/ELSE, %d IF/THEN, %d IF/ELSE & %d null IF.\n",
122 user_log(
"%d structured \"do ... while()\" %s been recovered.\n",
125 user_log(
"%d structured \"while() ...\" %s been recovered.\n",
140 list remove_continue_list =
NIL;
147 pips_debug(7,
"Dealing with unstructured %p (begin: %p, end: %p)\n",
148 u, entry_node, exit_node);
162 if (c != exit_node && c != entry_node)
182 pips_debug(7,
"\tNode %p has candidate links\n", c);
189 remove_continue_list);
190 pips_debug(7,
"\tNode %p for statement %s to be removed\n", c,
206 debug(3,
"remove_useless_continue_or_empty_code_in_unstructured",
207 "Remove control %p for statement %s\n", c,
211 remove_continue_list);
253 list control_nodes_to_fuse =
NIL;
262 hash_table controls_to_fuse_with_their_successors =
265 bool aggressive_restructure_p =
get_bool_property(
"FUSE_CONTROL_NODES_WITH_COMMENTS_OR_LABEL");
268 pips_debug(4,
"Begin with implicit target labels:");
284 pips_debug(3,
"Looking for control %p...\n", c);
294 pips_debug(3,
"Control %p: (gen_length(control_successors(c)) == 1), number_of_successors_of_the_successor = %zd, number_of_predecessors_of_the_successor = %zd, the successor is the entry node: %d, empty_statement_or_continue_p(control_statement(c)) = %d\n",
296 number_of_successors_of_the_successor,
297 number_of_predecessors_of_the_successor,
298 the_successor == entry_node,
309 if ((number_of_successors_of_the_successor <= 1
311 && the_successor != entry_node
312 && number_of_predecessors_of_the_successor == 1)
329 hash_put(controls_to_fuse_with_their_successors,
341 control_nodes_to_fuse);
345 pips_debug(3,
"(gen_length(control_successors(c)) == %zd)\n",
354 control_nodes_to_fuse =
gen_nreverse(control_nodes_to_fuse);
361 char * its_address_now;
364 its_address_now =
hash_get(controls_to_fuse_with_their_successors,
365 (
char *) the_original_control);
369 for(old_address = (
char *) the_original_control;;) {
370 pips_debug(3,
"Control %p (originally %p):\n",
371 its_address_now, the_original_control);
372 if (old_address == its_address_now
375 (
char *) its_address_now)
383 old_address = its_address_now;
385 =
hash_get(controls_to_fuse_with_their_successors,
386 (
char *) its_address_now);
389 a_control_to_fuse = (
control) its_address_now;
404 fprintf(stderr,
"Want to fuse control %p\n", a_control_to_fuse);
406 pips_assert(
"control a_control_to_fuse is consistent",
411 fprintf(stderr,
" with control %p\n", the_successor);
416 if (a_control_to_fuse == the_successor) {
417 pips_debug(3,
"\tA loop of control has been found... Do not fuse the control %p\n", a_control_to_fuse);
420 int number_of_successors_of_the_successor =
422 int number_of_predecessors_of_the_successor =
425 if ((number_of_successors_of_the_successor <= 1
427 && the_successor != entry_node
428 && number_of_predecessors_of_the_successor == 1)
445 if (the_successor == entry_node)
447 entry_node = a_control_to_fuse;
448 if (the_successor == exit_node)
449 exit_node = a_control_to_fuse;
457 (
char *) the_successor)) {
462 hash_update(controls_to_fuse_with_their_successors,
463 (
char *) the_successor,
464 (
char *) a_control_to_fuse);
468 pips_debug(3,
"\tDo not fuse them because the semantics have changed.\n");
475 control_nodes_to_fuse);
502 int entry_node_successors_length =
gen_length(entry_node_successors);
503 *new_unstructured_statement = s;
505 if (entry_node_successors_length == 2
511 if (entry_node_successors_length == 0) {
539 *new_unstructured_statement,
542 pips_assert(
"take_out_the_entry_node_of_the_unstructured",
543 entry_node_successors_length == 1);
563 try_to_structure_the_unstructured(
statement s,
566 control end_of_first_sequence, c;
567 list the_successors, the_predecessors;
568 list begin_statement_list =
NIL;
580 if (entry_node == exit_node)
583 end_of_first_sequence = entry_node;
590 end_of_first_sequence = c;
591 if (the_successors ==
NIL)
599 begin_statement_list =
601 end_of_first_sequence);
604 if (end_of_first_sequence != exit_node) {
611 begin_of_last_sequence = c;
625 if (the_successors !=
NIL)
629 begin_of_last_sequence =
CONTROL(
CAR(the_successors));
644 if (begin_statement_list !=
NIL || end_statement_list !=
NIL) {
645 if (end_of_first_sequence == exit_node) {
661 list list_of_the_new_statements;
666 *new_unstructured_statement,
669 if (begin_statement_list !=
NIL) {
673 list_of_the_new_statements =
gen_nconc(begin_statement_list,
674 list_of_the_new_statements);
682 end_of_first_sequence);
685 if (end_statement_list !=
NIL) {
687 list_of_the_new_statements =
gen_nconc(list_of_the_new_statements,
708 *new_unstructured_statement = s;
738 pips_assert(
"take_out_the_exit_node_if_not_a_continue :"
739 "The statement must be an unstructured",
759 the_exit_instruction =
766 list first_statement_list;
767 statement first_statement, last_statements;
769 list the_statements =
771 pips_assert(
"the_statements must be a true sequence",
776 first_statement_list = the_statements;
778 the_statements =
CDR(the_statements);
779 CDR(first_statement_list) =
NIL;
782 last_statements = the_exit_statement;
799 the_exit_statement = first_statement;
823 the_unstructured = new_statement;
831 return the_unstructured;
856 test_exit = then_node;
933 bool code_modified_p =
false;
953 int then_node_fan_out =
957 int then_node_fan_in =
959 + (then_node == entry_node);
960 int else_node_fan_out =
962 int else_node_fan_in =
964 + (else_node == entry_node);
966 if (then_node == else_node) {
975 else if (then_node_fan_out == 1
976 && else_node_fan_out == 1
977 && then_node_fan_in == 1
978 && else_node_fan_in == 1
986 else if (then_node_fan_out == 1
987 && then_node_fan_in == 1
996 else if (else_node_fan_out == 1
997 && else_node_fan_in == 1
1012 debug(5,
"restructure_if_then_else",
1013 "%d if/then, %d if/else, %d if/then/else, %d null if\n",
1028 code_modified_p =
true;
1033 return code_modified_p;
1052 pips_debug(5,
"after fuse_sequences_in_unstructured\n");
1067 new_unstructured_statement =
1071 pips_debug(5,
"after take_out_the_exit_node_if_not_a_continue\n");
1080 pips_debug(5,
"after restructure_if_then_else\n");
1117 pips_debug(5,
"after remove_the_unreachable_controls_of_an_unstructured\n");
1118 pips_debug(5,
"Accessible nodes from entry:\n");
1120 pips_debug(5,
"Accessible nodes from exit:\n");
1129 pips_debug(5,
"after remove_useless_continue_or_empty_code_in_unstructured\n");
1148 pips_debug(2,
"At entry, from the entry node:\n");
1172 if (then_c == entry_node && else_c == exit_node) {
1181 else if (then_c == exit_node && else_c == entry_node) {
1225 if (else_c == exit_node) {
1226 if (then_c == entry_node) {
1245 body_control = then_c;
1251 else if (then_c == exit_node) {
1252 if (else_c == entry_node) {
1274 body_control = else_c;
1323 pips_debug(2,
"After while recovering, from the entry node:\n");
1344 debug_on(
"UNSPAGHETTIFY_DEBUG_LEVEL");
void user_log(const char *format,...)
bool unstructured_consistent_p(unstructured p)
bool statement_consistent_p(statement p)
void free_instruction(instruction p)
bool control_consistent_p(control p)
void free_statement(statement p)
bool clean_up_sequences_internal(statement s)
An entry point for internal usage, such as from take_out_the_exit_node_if_not_a_continue():
bool clean_up_sequences(statement s)
Recursively clean up the statement sequences by fusing them if possible and by removing useless one.
struct _newgen_struct_statement_ * statement
void control_graph_recursive_decomposition(unstructured)
hierarchize.c
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define gen_recurse(start, domain_number, flt, rwt)
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
void unlink_2_control_nodes(control source, control target)
Remove all edged between 2 control nodes.
void remove_all_unreachable_controls_of_an_unstructured(unstructured u)
Remove all control nodes that are not forward reachable from the entry node.
void display_linked_control_nodes(control c)
Display all the control nodes reached or reachable from c for debugging purpose.
void link_2_control_nodes(control source, control target)
Add an edge between 2 control nodes.
void remove_a_control_from_an_unstructured_without_relinking(control c)
It removes a control node from its successor and predecessor.
void discard_an_unstructured_without_its_statements(unstructured u)
Used to discard an unstructured without touching its statements.
void remove_a_control_from_an_unstructured(control c)
Remove a control node from a control graph.
void discard_a_control_sequence_without_its_statements(control begin, control end)
Remove a control sequence without touching its statements.
void fuse_2_control_nodes(control first, control second)
Fuse a 2 control nodes.
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....
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an unstructured.
void reset_current_module_entity(void)
Reset the current module entity.
void reset_current_module_statement(void)
Reset the current module statement.
statement set_current_module_statement(statement)
Set the current module statement.
entity set_current_module_entity(entity)
static.c
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
list gen_nreverse(list cp)
reverse a list in place
#define NIL
The empty list (nil in Lisp)
size_t gen_length(const list l)
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
#define CAR(pcons)
Get the value of the first element of a list.
void gen_free_list(list l)
free the spine of the list
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
#define CDR(pcons)
Get the list less its first element.
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
bool unlabelled_statement_p(statement)
bool nop_statement_p(statement)
bool empty_statement_or_continue_p(statement)
Return true if the statement is an empty instruction block or a continue or a recursive combination o...
bool empty_statement_or_continue_without_comment_p(statement)
Return true if the statement is an empty instruction block or a continue without comments or without ...
list statement_to_implicit_target_labels(statement)
Look for labels appearing in END= or ERR= IO clauses and allocate a label list.
entity statement_to_label(statement)
See if statement s is labelled and can be reached by a GO TO.
statement make_whileloop_statement(expression, statement, int, bool)
Build a while loop statement.
void put_formats_at_module_beginning(statement)
Transfer all the FORMATs at the very beginning of a module:
string statement_identification(statement)
Like external_statement_identification(), but with internal information, the hexadecimal address of t...
bool return_statement_p(statement)
Test if a statement is a C or Fortran "return".
void put_formats_at_module_end(statement)
Transfer all the FORMATs at the very end of a module:
statement make_continue_statement(entity)
bool statement_with_empty_comment_p(statement)
Return true if the statement has an empty statement:
hash_table hash_table_make(hash_key_type key_type, size_t size)
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
void hash_update(hash_table htp, const void *key, const void *val)
update key->val in htp, that MUST be pre-existent.
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
struct _newgen_struct_control_ * control
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
#define pips_user_warning
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
#define pips_internal_error
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
void print_arguments(list args)
#define HASH_MAP(k, v, code, ht)
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define C_NOT_OPERATOR_NAME
#define empty_comments
Empty comments (i.e.
#define make_empty_statement
An alias for make_empty_block_statement.
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
entity entity_empty_label(void)
entity CreateIntrinsic(string name)
this function does not create an intrinsic function because they must all be created beforehand by th...
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
#define control_undefined
#define instruction_sequence_p(x)
#define unstructured_domain
newgen_type_domain_defined
#define control_predecessors(x)
#define statement_domain
newgen_sizeofexpression_domain_defined
#define CONTROL(x)
CONTROL.
#define statement_label(x)
#define expression_undefined
#define sequence_statements(x)
#define instruction_sequence(x)
#define control_successors(x)
#define unstructured_exit(x)
#define instruction_unstructured_p(x)
#define test_condition(x)
#define statement_instruction(x)
#define statement_comments(x)
#define control_statement(x)
#define instruction_test(x)
#define statement_number(x)
#define instruction_unstructured(x)
#define statement_undefined
#define STATEMENT(x)
STATEMENT.
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
The structure used to build lists in NewGen.
@ N_ITER_RESTRUCTURE_FIX_POINT
static int number_of_recovered_do_while
static void display_unspaghettify_statistics()
static int number_of_restructured_if_then_else
bool unspaghettify(const string mod_name)
Try to simplify the control graph of a module by removing useless CONTINUEs, unreachable code.
bool restructure_control(const string mod_name)
Try to simplify the control graph of a module by removing useless CONTINUEs, unreachable code,...
static int number_of_restructured_null_if
static int total_number_of_restructurations()
Compute the number of all the computations that have been done.
static void clean_up_exit_node(unstructured u)
The controlizer of PIPS seems to have a bug: it put an empty successor node to the so-called exit nod...
static void initialize_unspaghettify_statistics()
static int number_of_restructured_if_then
To print some statistics about control graph restructuration:
void unspaghettify_or_restructure_statement(statement mod_stmt)
The entry point common to unspaghettify or restructure a module:
void simple_restructure_statement(statement mod_stmt)
A simple cleaning of the control graph without major topological restructuring.
static void recursively_restructure_an_unstructured(statement s)
Try to recursively restructure the unstructured:
statement take_out_the_exit_node_if_not_a_continue(statement s)
Extract the statement from an exit node of an unstructured statement if it is a useful statement.
static void remove_useless_continue_or_empty_code_in_unstructured(unstructured u)
Remove a useless continue in a sequence of control since it is typically the kind of useless things g...
void restructure_statement(statement mod_stmt)
The real entry point of control graph restructuring:
static void recover_structured_while(unstructured u)
Try to recover structured while loops in an already recursively restructured control graph.
void fuse_sequences_in_unstructured(statement s)
Try to transform each control sequence in a single statement instead of a list of control nodes:
static int number_of_restructured_if_else
void unspaghettify_statement(statement mod_stmt)
The real entry point of unspaghettify:
static bool restructure_if_then_else(statement s)
Try to restructure the unstructured IF/THEN/ELSE.
static void restructure_this_test(control c, structured_test_type t)
static bool take_out_the_entry_node_of_the_unstructured(statement s, statement *new_unstructured_statement)
Take the entry node out of the unstructured if it is not useful, such as not an IF or a node without ...
static int number_of_recovered_while
static void clean_up_control(statement s)
This is the function that is applied on each statement of the code in a bottom-up way to clean up eas...
char vcid_unspaghettify[]
Ronan Keryell, 1995.
static bool __attribute__((unused))
If the unstructured begin and/or end with a sequence, move the sequence(s) out of the unstructured an...
static bool currently_apply_recursive_decomposition
@ STRUCTURED_IF_THEN_ELSE
static bool currently_apply_test_restructuring