PIPS
|
Go to the source code of this file.
Macros | |
#define | CONTROL_INCLUDED |
Warning! Do not modify this file that is automatically generated! More... | |
#define | USE_NEW_CONTROLIZER_ENV_VAR_NAME "PIPS_USE_NEW_CONTROLIZER" |
Define the environment variables used to select which controlizer version to use independently of which one was activated at the pipsmake level: More... | |
#define | USE_OLD_CONTROLIZER_ENV_VAR_NAME "PIPS_USE_OLD_CONTROLIZER" |
The name of the one to force the use of the old controlizer: More... | |
Functions | |
statement | unsugared_loop_header (statement) |
LOOP_HEADER, LOOP_TEST and LOOP_INC build the desugaring phases of a do-loop L for the loop header (i=1), the test (i<10) and the increment (i=i+1). More... | |
statement | unsugared_forloop_header (statement) |
statement | unsugared_whileloop_header (statement) |
statement | unsugared_loop_test (statement) |
Do a crude test of end of do-loop for do-loop unsugaring. More... | |
statement | unsugared_forloop_test (statement) |
statement | unsugared_whileloop_test (statement) |
statement | unsugared_loop_inc (statement) |
Do an index increment instruction for do-loop unsugaring. More... | |
statement | unsugared_forloop_inc (statement) |
control | find_exit_control_node (list, control) |
Find the exit node of a sub-CFG defined by the list of nodes ctls and by the first node to execute when finished. More... | |
control | find_or_create_exit_control_node (list, control) |
FI: remake of function above, incomplete backward approach, now obsolete because the forward approach works. More... | |
bool | controlize_statement (control, control, hash_table) |
Controlize a statement that is in a control node, that is restructure it to have a HCFG recursively (a hierarchical control flow graph). More... | |
statement | hcfg (statement) |
Compute the hierarchical control flow graph (HCFG) of a statement. More... | |
statement | loop_header (statement) |
LOOP_HEADER, LOOP_TEST and LOOP_INC build the desugaring phases of a do-loop L for the loop header (i=1), the test (i<10) and the increment (i=i+1). More... | |
statement | loop_test (statement) |
statement | loop_inc (statement) |
statement | forloop_header (statement) |
statement | forloop_test (statement) |
statement | forloop_inc (statement) |
unstructured | control_graph (statement) |
CONTROL_GRAPH returns the control graph of the statement ST. More... | |
bool | ctrl_graph_undefined_p (void) |
graph.c More... | |
void | reset_ctrl_graph (void) |
void | error_reset_ctrl_graph (void) |
void | set_ctrl_graph (controlmap) |
controlmap | get_ctrl_graph (void) |
void | init_ctrl_graph (void) |
void | close_ctrl_graph (void) |
void | store_ctrl_graph (statement, control) |
void | update_ctrl_graph (statement, control) |
control | load_ctrl_graph (statement) |
control | delete_ctrl_graph (statement) |
bool | bound_ctrl_graph_p (statement) |
void | store_or_update_ctrl_graph (statement, control) |
void | clean_ctrl_graph (void) |
global mapping from statements to their control in the full control graph More... | |
list | control_list_to_statement_list (list) |
of statement More... | |
void | build_full_ctrl_graph (statement) |
void | full_control_graph (string) |
FULL CONTROL GRAPH for module NAME. More... | |
void | init_ctrl_graph_travel (statement, bool(*)(statement)) |
bool | next_ctrl_graph_travel (statement *) |
void | close_ctrl_graph_travel (void) |
void | control_graph_recursive_decomposition (unstructured) |
hierarchize.c More... | |
bool | new_controlizer (const char *) |
module.c More... | |
bool | controlizer (const char *) |
The old controlizer user interface. More... | |
void | fuse_sequences_in_unstructured (statement) |
Try to transform each control sequence in a single statement instead of a list of control nodes: More... | |
statement | take_out_the_exit_node_if_not_a_continue (statement) |
Extract the statement from an exit node of an unstructured statement if it is a useful statement. More... | |
void | unspaghettify_or_restructure_statement (statement) |
The entry point common to unspaghettify or restructure a module: More... | |
void | unspaghettify_statement (statement) |
The real entry point of unspaghettify: More... | |
void | simple_restructure_statement (statement) |
A simple cleaning of the control graph without major topological restructuring. More... | |
bool | unspaghettify (const string) |
Try to simplify the control graph of a module by removing useless CONTINUEs, unreachable code. More... | |
void | restructure_statement (statement) |
The real entry point of control graph restructuring: More... | |
bool | restructure_control (const string) |
Try to simplify the control graph of a module by removing useless CONTINUEs, unreachable code, etc. More... | |
bool | unstructured_consistency_p (unstructured, bool) |
cfg.c More... | |
bool | unstructured_while_p (unstructured) |
Test if an unstructured is found to be like a structured while-loop. More... | |
void | init_reachable (statement) |
unreachable.c More... | |
bool | statement_reachable_p (statement) |
Test if the given statement is reachable from some statements given at init_reachable(start) More... | |
bool | statement_continued_p (statement) |
Test if the execution goes on after the given statement. More... | |
void | close_reachable (void) |
Remove reachability information about previously checked statements. More... | |
bool | meaningless_control_p (control) |
bourdoncle.c More... | |
bool | control_test_p (control) |
Check that a node is used as a test in a CFG. More... | |
void | add_control_to_embedding_control_list (control) |
control | control_to_ancestor (control, hash_table) |
If vertex is an ancestor control node from the input control graph, return vertex, else return its ancestor. More... | |
control | control_shallow_copy (control) |
unstructured | unstructured_shallow_copy (unstructured, hash_table) |
unstructured | partition_to_unstructured (control, list) |
Build a new unstructured (CFG) for partition. More... | |
void | intersect_successors_with_partition_or_complement (control, list, bool) |
If complement_p, preserve successors in the complement of partition. More... | |
void | intersect_successors_with_partition (control, list) |
void | intersect_successors_with_partition_complement (control, list) |
list | bourdoncle_partition (unstructured, unstructured *, hash_table *, hash_table *) |
list | bourdoncle_component (control, hash_table, hash_table) |
int | bourdoncle_visit (control, list *, hash_table, hash_table) |
unstructured | ancestor_cycle_head_to_scc (control, hash_table) |
scc_map maps either the ancestor node to its scc if the transformers are computed without context, or the call site node to its scc if cycles are replicated to compute transformers within their context. More... | |
unstructured | proper_cycle_head_to_scc (control, hash_table) |
Retrieve a scc_u from its head. More... | |
bool | cycle_head_p (control, hash_table, hash_table) |
This node is a cycle call site. More... | |
bool | proper_cycle_head_p (control, hash_table) |
This node is really the head of a cycle (red on daVinci pictures). More... | |
bool | direct_cycle_head_p (control, hash_table) |
This node is directly associated to a specific cycle. More... | |
unstructured | cycle_head_to_scc (control, hash_table, hash_table) |
The ancestor of this node is associated to a specific cycle. More... | |
bool | one_successor_kind_only_p (control, bool) |
useful for non-deterministic control flow graph only More... | |
bool | true_successors_only_p (control) |
bool | false_successors_only_p (control) |
void | bourdoncle_free (unstructured, hash_table, hash_table) |
bool | guess_late_read_effect_on_entity (expression, entity) |
for_to_do_or_while_loops.c More... | |
sequence | for_to_do_loop_conversion (forloop, statement) |
Try to convert a C-like for-loop into a Fortran-like do-loop. More... | |
void | try_to_transform_a_for_loop_into_a_do_loop (forloop) |
Try to to transform the C-like for-loops into Fortran-like do-loops. More... | |
bool | for_loop_to_do_loop (const string) |
For-loop to do-loop transformation phase. More... | |
sequence | for_to_while_loop_conversion (expression, expression, expression, statement, extensions) |
Build a sequence with a while-loop from for-loop parameters. More... | |
void | transform_a_for_loop_into_a_while_loop (forloop) |
Try to to transform the C-like for-loops into Fortran-like do-loops. More... | |
void | transform_a_for_loop_statement_into_a_while_loop (statement) |
Same as above, but with no calls to ancestors. More... | |
bool | for_loop_to_while_loop (const string) |
For-loop to while-loop transformation phase. More... | |
bool | dowhile_to_while (const char *) |
dowhile_to_while.c More... | |
void | do_loop_to_while_loop (statement) |
converts a doloop to a while loop, in place More... | |
void | do_loop_to_for_loop (statement) |
converts a doloop to a for loop, in place More... | |
Variables | |
char | vcid_control_controlizer [] |
cproto-generated files More... | |
char | vcid_control_old_controlizer [] |
old_controlizer.c More... | |
char | vcid_unspaghettify [] |
unspaghettify.c More... | |
#define CONTROL_INCLUDED |
Warning! Do not modify this file that is automatically generated!
Modify src/Libs/control/control-local.h instead, to add your own modifications. header file built by cproto control-local.h – control.h
#define USE_NEW_CONTROLIZER_ENV_VAR_NAME "PIPS_USE_NEW_CONTROLIZER" |
#define USE_OLD_CONTROLIZER_ENV_VAR_NAME "PIPS_USE_OLD_CONTROLIZER" |
void add_control_to_embedding_control_list | ( | control | c | ) |
Definition at line 535 of file bourdoncle.c.
References CONS, CONTROL, and embedding_control_list.
Referenced by node_to_linked_nodes(), and print_embedding_graph().
unstructured ancestor_cycle_head_to_scc | ( | control | a, |
hash_table | scc_map | ||
) |
scc_map maps either the ancestor node to its scc if the transformers are computed without context, or the call site node to its scc if cycles are replicated to compute transformers within their context.
In spite of the name, this function can be call with ANY control, ancestor or not. An ancestor or a call site are mapped to a defined value.
scc_map | cc_map |
Definition at line 2356 of file bourdoncle.c.
References hash_get(), HASH_UNDEFINED_VALUE, and unstructured_undefined.
Referenced by cycle_head_p(), cycle_head_to_scc(), cycle_to_flow_sensitive_preconditions(), dag_to_flow_sensitive_preconditions(), direct_cycle_head_p(), load_control_fix_point(), and replicate_cycles().
list bourdoncle_component | ( | control | vertex, |
hash_table | ancestor_map, | ||
hash_table | scc_map | ||
) |
bourdoncle partition
Build sub-unstructured associated to vertex and partition
Re-use copying performed in scc_to_dag() instead u = partition_to_unstructured(vertex, partition); vertex_ancestor = control_to_ancestor(vertex, ancestor_map); hash_put(scc_map, vertex_ancestor, u);
The partition may have to be refreshed because of the previous recursive descent and its graph restructuring action. It is assumed that vertex is still good because heads are not: however vertex is not an ancestor because the input unstructured is copied right away by bourdoncle_partition().
It might be better to recompute the smallest scc including vertex...
Update parent unstructured containing vertex and partition, remove partition and return a new unstructured with the partition inside, except for the initial vertex node which is left in the embedding graph
Build sub-unstructured associated to vertex and partition
u = unlink_partition_and build_unstructured(vertex, partition);
Do not go down into nested unstructured
vertex | ertex |
ancestor_map | ncestor_map |
scc_map | cc_map |
Definition at line 2218 of file bourdoncle.c.
References bourdoncle_visit(), CONS, CONTROL, control_domain, control_successors, control_to_ancestor(), control_undefined, gen_copy_seq(), gen_false(), gen_free_list(), gen_multi_recurse(), gen_null(), gen_true(), get_dfn(), hash_put(), ifdebug, list_undefined, MAP, NIL, pips_debug, print_control_node_b(), print_control_nodes(), scc_to_dag(), statement_domain, unstructured_control, unstructured_exit, unstructured_undefined, and update_partition().
Referenced by bourdoncle_visit().
void bourdoncle_free | ( | unstructured | ndu, |
hash_table | ancestor_map, | ||
hash_table | scc_map | ||
) |
Do not free the statements pointed by the nodes in ndu or in the scc
ndu | du |
ancestor_map | ncestor_map |
scc_map | cc_map |
Definition at line 2506 of file bourdoncle.c.
References bourdoncle_unstructured_free(), HASH_MAP, and hash_table_free().
Referenced by unstructured_to_flow_sensitive_postconditions_or_transformers().
list bourdoncle_partition | ( | unstructured | u, |
unstructured * | p_ndu, | ||
hash_table * | p_ancestor_map, | ||
hash_table * | p_scc_map | ||
) |
DAG derived from u by elimination all cycles
mapping from nodes in the new unstructured to the node in the input unstructured
mapping from nodes in u, used as cycle breakers, to the corresponding scc represented as an unstructured
Initialize dfn to 0
Start from the entry point
Should the partition be translated?
Should the cycles be replicated to refine the analyses? If yes, replicate them.
Control nodes associated to a fix point
The hierarchy of fix points is/seems to be lost by scc_map...
We also need the final embedding graph... which might be lost? Or hanging from the first node in partition, the entry point, and hence from new_u.
p_ndu | _ndu |
p_ancestor_map | _ancestor_map |
p_scc_map | _scc_map |
Definition at line 1902 of file bourdoncle.c.
References bourdoncle_visit(), control_domain, control_undefined, davinci_print_non_deterministic_unstructured(), dfn, fprintf(), gen_false(), gen_multi_recurse(), gen_null(), gen_true(), get_bool_property(), hash_get(), HASH_MAP, hash_pointer, hash_table_free(), hash_table_make(), HASH_UNDEFINED_VALUE, ifdebug, NIL, num, pips_debug, print_control_nodes(), print_unstructured(), replicate_cycles(), reset_dfn(), set_davinci_count(), statement_domain, unstructured_control, unstructured_shallow_copy(), and unstructured_undefined.
Referenced by unstructured_to_flow_sensitive_postconditions_or_transformers().
int bourdoncle_visit | ( | control | vertex, |
list * | ppartition, | ||
hash_table | ancestor_map, | ||
hash_table | scc_map | ||
) |
vertex | ertex |
ppartition | partition |
ancestor_map | ncestor_map |
scc_map | cc_map |
Definition at line 2293 of file bourdoncle.c.
References bourdoncle_component(), CONS, CONTROL, control_successors, gen_nconc(), get_dfn(), MAP, min, num, and update_dfn().
Referenced by bourdoncle_component(), and bourdoncle_partition().
void build_full_ctrl_graph | ( | statement | s | ) |
first pass to initialize the ctrl_graph controls
STATEMENT
second pass to link the statements
Definition at line 238 of file graph.c.
References gen_multi_recurse(), gen_true(), init_ctrl_graph(), NIL, ORDERING_NUMBER, ORDERING_STATEMENT, pips_debug, statement_arrows(), statement_domain, statement_number, statement_ordering, and stmt_rewrite().
Referenced by full_control_graph(), and handle_hpf_directives().
void clean_ctrl_graph | ( | void | ) |
global mapping from statements to their control in the full control graph
the crtl_graph is freed by hand, because the default behavior is not convenient for my purpose. I would have needed a persistant statement in the control, but it is not desired in pips.
now it can be freed safely
Definition at line 53 of file graph.c.
References close_ctrl_graph(), control_predecessors, control_statement, control_successors, CONTROLMAP_MAP, gen_free_list(), get_ctrl_graph(), NIL, ORDERING_NUMBER, ORDERING_STATEMENT, pips_debug, statement_ordering, and statement_undefined.
Referenced by handle_hpf_directives().
void close_ctrl_graph | ( | void | ) |
void close_ctrl_graph_travel | ( | void | ) |
Definition at line 340 of file graph.c.
Referenced by handle_independent_directive(), handle_reduction_directive(), and propagate_synonym().
void close_reachable | ( | void | ) |
Remove reachability information about previously checked statements.
Definition at line 252 of file unreachable.c.
Referenced by module_name_to_preconditions(), and module_name_to_total_preconditions().
void control_graph_recursive_decomposition | ( | unstructured | u | ) |
Have a look to paper "A Control-Flow Normalization Algorithm and Its Complexity" (1994) from Zahira Ammarguellat for a bibliography of the domain.
An interval graph is represented by a graph with interval_vertex_label decorations embedding control nodes. The first interval of the graph is the entry interval of the interval graph and the first control node of an interval is the entry control node of the interval:
The seed interval graph is indeed the control graph itself:
Apply recursively interval graph decomposition:
For all intervals of the graph:
If this interval has at most one exit it should be put in its own unstructured:
Useless to restructure the exit node...
If a single node, only useful if there is a loop inside (in order to detect these loops, hierarchize_control_list() is called before interval_graph() but then we need to add more guards...):
If an interval has at most one exit, the underlaying control graph can be hierachized by an unstructured.
Put all the controls in their own unstructured to hierarchize the graph:
Skip the entry interval
Stop if the interval graph does no longer change : it is only one node or an irreductible graph:
Construct the interval graph from the previous one:
Do not forget to detach control nodes from interval before sweeping:
Definition at line 563 of file hierarchize.c.
References CAR, CDR, CONTROL, control_graph_to_interval_graph_format(), control_successors, control_undefined, debug_off, debug_on, display_interval_graph(), display_linked_control_nodes(), free_graph(), gen_free_list(), gen_length(), graph_vertices, hierarchize_control_list(), ifdebug, interval_exit_nodes(), interval_graph(), interval_vertex_label_controls, MAP, NIL, pips_assert, pips_debug, unstructured_consistent_p(), unstructured_control, unstructured_exit, VERTEX, and vertex_vertex_label.
Referenced by unspaghettify_or_restructure_statement().
of statement
of statements
lc | c |
Definition at line 103 of file graph.c.
References CONS, CONTROL, control_statement, MAP, NIL, and STATEMENT.
Referenced by compute_cumulated_reductions(), and statement_arrows().
Definition at line 970 of file bourdoncle.c.
References control_predecessors, control_statement, control_successors, control_undefined, gen_copy_seq(), hash_put(), make_control(), and replicate_map.
Referenced by partition_to_unstructured(), and unstructured_shallow_copy().
Check that a node is used as a test in a CFG.
The associated statement must be a test, the number of successors must be two and the true and false branches must be empty. Exported for user of ND CFG's.
Definition at line 175 of file bourdoncle.c.
References control_statement, control_successors, empty_statement_or_labelless_continue_p(), gen_length(), meaningless_control_p(), statement_test(), statement_test_p(), test_false, and test_true.
Referenced by add_test_successor(), clean_up_embedding_graph(), dag_to_flow_sensitive_preconditions(), davinci_print_control_node(), intersect_successors_with_partition_or_complement(), load_arc_precondition(), one_successor_kind_only_p(), process_ready_node(), update_successor_in_copy(), and update_successors_of_predecessor().
control control_to_ancestor | ( | control | vertex, |
hash_table | ancestor_map | ||
) |
If vertex is an ancestor control node from the input control graph, return vertex, else return its ancestor.
Is used in other libraries.
This assert may be too strong, but all control nodes are copied when just after entering bourdoncle_partition which should make it correct.
Theoretically only useful when HASH_UNDEFINED_VALUE has been returned, i.e. when ancestor==vertex
vertex | ertex |
ancestor_map | ncestor_map |
Definition at line 854 of file bourdoncle.c.
References ancestor_control_p(), control_statement, control_undefined, hash_get(), HASH_UNDEFINED_VALUE, ifdebug, pips_assert, pips_debug, and statement_identification().
Referenced by bourdoncle_component(), cycle_head_p(), cycle_head_to_scc(), cycle_to_flow_sensitive_preconditions(), dag_or_cycle_to_flow_sensitive_postconditions_or_transformers(), dag_to_flow_sensitive_preconditions(), load_control_fix_point(), load_cycle_temporary_precondition(), replicate_cycles(), and update_partition().
bool controlizer | ( | const char * | module_name | ) |
The old controlizer user interface.
Transform a code with some goto and labels (typically generated by a parser) into a code that is a hierarchical control flow graph, the standard abstract syntax tree of PIPS (the RI).
Interface for pipsdbm and pipsmake
Should never arise
To have the debug in unspaghettify_statement() working:
The statement of a compilation unit is a long list of continue statements and it takes a long time to restructure although nothing is done in the end. So, let's skip this useless processing. SG:it may be ok to skip it, but we still need to call module_reorder ...
gen_copy_seq(statement_declarations(parsed_mod_stat))
By setting this property, we try to unspaghettify the control graph of the module:
With C code, some local declarations may have been lost by the (current) restructurer
Reorder the module, because we have a new statement structure.
module_name | odule_name |
Definition at line 224 of file module.c.
References c_module_p(), code_language, compilation_unit_p(), control_graph(), copy_statement(), db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, empty_comments, empty_extensions(), entity_empty_label(), entity_initial, entity_undefined_p, get_bool_property(), ifdebug, is_instruction_unstructured, is_language_fortran, language_tag, make_instruction(), MAKE_ORDERING, make_statement(), make_synchronization_none(), module_name(), module_name_to_entity(), module_reorder(), new_controlizer(), NIL, pips_assert, pips_user_warning, reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), set_prettyprint_language_from_property(), statement_consistent_p(), STATEMENT_NUMBER_UNDEFINED, unspaghettify_statement(), update_unstructured_declarations(), USE_NEW_CONTROLIZER_ENV_VAR_NAME, value_code, and value_code_p.
Referenced by AddEntityToCompilationUnit(), new_controlizer(), outliner_independent(), and RemoveEntityFromCompilationUnit().
bool ctrl_graph_undefined_p | ( | void | ) |
graph.c
bool cycle_head_p | ( | control | c, |
hash_table | ancestor_map, | ||
hash_table | scc_map | ||
) |
This node is a cycle call site.
This is correct whether the actual scc associated to c is scc_u or not. If a copy of a control is associated to a scc, its ancestors and all the others copies also are associated to a scc.
we may be in the context sensitive transformer mode
ancestor_map | ncestor_map |
scc_map | cc_map |
Definition at line 2385 of file bourdoncle.c.
References ancestor_cycle_head_to_scc(), control_to_ancestor(), and unstructured_undefined_p.
Referenced by cycle_to_flow_sensitive_preconditions(), dag_to_flow_sensitive_preconditions(), davinci_print_non_deterministic_unstructured(), process_ready_node(), replicate_cycles(), and unstructured_to_effects().
unstructured cycle_head_to_scc | ( | control | c, |
hash_table | ancestor_map, | ||
hash_table | scc_map | ||
) |
The ancestor of this node is associated to a specific cycle.
either we have a direct connection, or we need to go thru the ancestor node
ancestor_map | ncestor_map |
scc_map | cc_map |
Definition at line 2433 of file bourdoncle.c.
References ancestor_cycle_head_to_scc(), control_to_ancestor(), and unstructured_undefined_p.
Referenced by dag_to_flow_sensitive_preconditions(), process_ready_node(), and unstructured_to_effects().
bool direct_cycle_head_p | ( | control | c, |
hash_table | scc_map | ||
) |
This node is directly associated to a specific cycle.
scc_map | cc_map |
Definition at line 2422 of file bourdoncle.c.
References ancestor_cycle_head_to_scc(), and unstructured_undefined_p.
Referenced by replicate_cycles().
void do_loop_to_for_loop | ( | statement | sl | ) |
converts a doloop to a for loop, in place
sl | l |
Definition at line 162 of file dowhile_to_while.c.
References copy_expression(), copy_statement(), entity_intrinsic(), entity_to_expression(), LESS_OR_EQUAL_OPERATOR_NAME, loop_body, loop_index, loop_range, make_assign_expression(), make_forloop(), make_instruction_forloop(), MakeBinaryCall(), pips_assert, PLUS_UPDATE_OPERATOR_NAME, range_increment, range_lower, range_upper, statement_loop(), statement_loop_p(), and update_statement_instruction().
Referenced by rw_loop().
void do_loop_to_while_loop | ( | statement | sl | ) |
converts a doloop to a while loop, in place
convert the loop to a while loop : fst the body
then the whileloop
and the prelude
sl | l |
Definition at line 115 of file dowhile_to_while.c.
References copy_statement(), entity_empty_label(), entity_intrinsic(), entity_to_expression(), expression_undefined, instruction_to_statement(), LESS_OR_EQUAL_OPERATOR_NAME, loop_body, loop_index, loop_range, make_assign_statement(), make_block_statement(), make_evaluation_before(), make_instruction_sequence(), make_instruction_whileloop(), make_sequence(), make_statement_list, make_whileloop(), MakeBinaryCall(), pips_assert, PLUS_OPERATOR_NAME, range_increment, range_lower, range_upper, statement_loop(), statement_loop_p(), and update_statement_instruction().
Referenced by terapix_loop_handler().
bool dowhile_to_while | ( | const char * | module_name | ) |
module_name | odule_name |
Definition at line 82 of file dowhile_to_while.c.
References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, dowhile_to_while_walker(), gen_context_recurse, gen_true2(), get_current_module_statement(), module_name(), module_name_to_entity(), module_reorder(), reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), and statement_domain.
void error_reset_ctrl_graph | ( | void | ) |
Definition at line 2481 of file bourdoncle.c.
References one_successor_kind_only_p().
Referenced by dag_to_flow_sensitive_preconditions(), and process_ready_node().
For-loop to do-loop transformation phase.
This transformation transform for example a \begin{lstlisting} for (i = lb; i < ub; i += stride) body; \end{lstlisting} into a \begin{lstlisting}[language=fortran] do i = lb, ub - 1, stride body end do \end{lstlisting}
Now use pure local analysis on the code but we could imagine further use of semantics analysis some day...
Get the true ressource, not a copy, since we modify it in place.
We need to access to the instruction containing the current for-loops, so ask NewGen gen_recurse to keep this informations for us:
Iterate on all the for-loops:
Reorder the module, because some statements have been replaced.
Should have worked:
module_name | odule_name |
Definition at line 779 of file for_to_do_or_while_loops.c.
References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, forloop_domain, gen_recurse, gen_true(), module_name(), module_name_to_entity(), module_reorder(), module_statement, pips_assert, pips_debug, reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), statement_consistent_p(), and try_to_transform_a_for_loop_into_a_do_loop().
For-loop to while-loop transformation phase.
This transformation transforms a \begin{lstlisting} for (init; cond; update) body; \end{lstlisting} into a \begin{lstlisting} { init; while(cond) { body; update; } } \end{lstlisting}
Get the true ressource, not a copy, since we modify it in place.
We need to access to the instruction containing the current for-loops, so ask NewGen gen_recurse to keep this informations for us:
Iterate on all the for-loops:
Reorder the module, because some statements have been replaced.
Should have worked:
module_name | odule_name |
Definition at line 1001 of file for_to_do_or_while_loops.c.
References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, gen_recurse, gen_true(), module_name(), module_name_to_entity(), module_reorder(), module_statement, pips_assert, pips_debug, reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), statement_consistent_p(), statement_domain, and transform_a_for_loop_statement_into_a_while_loop().
Try to convert a C-like for-loop into a Fortran-like do-loop.
Assume to match what is done in the prettyprinter C_loop_range().
This does not filter scalar integers...
Consider only scalar integer variables as loop indices
&& type_depth(lit)==1
We got a candidate loop index and final bound, let's check the increment
We have found a do-loop compatible for-loop:
guess lower bound
try hard to reproduce statement content
theloop | heloop |
parent | arent |
Definition at line 614 of file for_to_do_or_while_loops.c.
References call_arguments, CAR, CDR, condition_expression_to_final_bound(), CONS, empty_comments, empty_extensions(), entity_empty_label(), entity_local_name(), entity_to_expression(), entity_type, EXPRESSION, expression_call(), expression_undefined_p, forloop_body, forloop_condition, forloop_increment, forloop_initialization, gen_append(), get_referenced_entities(), guess_late_read_effect_on_entity(), guess_loop_increment(), guess_loop_lower_bound(), guess_write_effect_on_entity(), incrementation_expression_to_increment(), init, insert_statement(), instruction_to_statement(), loop_index, make_execution_sequential(), make_instruction_call(), make_instruction_expression(), make_instruction_loop(), make_loop(), make_range(), make_sequence(), make_statement(), make_synchronization_none(), NIL, pips_user_warning, remove_expression_from_comma_list(), scalar_integer_type_p(), sequence_statements, sequence_undefined, SET_FOREACH, set_free(), set_intersection(), set_make(), set_pointer, STATEMENT, statement_comments, statement_declarations, statement_decls_text, statement_extensions, statement_label, statement_number, STATEMENT_NUMBER_UNDEFINED, statement_ordering, STATEMENT_ORDERING_UNDEFINED, and ultimate_type().
Referenced by controlize_forloop(), and try_to_transform_a_for_loop_into_a_do_loop().
sequence for_to_while_loop_conversion | ( | expression | init, |
expression | cond, | ||
expression | incr, | ||
statement | body, | ||
extensions | exts | ||
) |
Build a sequence with a while-loop from for-loop parameters.
The API is a little weird to comply with the controlizer implementation...
Build the loop body of the while with { body; incr_st; } :
Build the while(cond) { n_body } statement:
pips_debug(5, "Initialization statement:\n");
print_statement(init_st);
pips_debug(5, "Incrementation statement:\n");
print_statement(incr_st);
pips_debug(5, "New body statement with incrementation:\n");
print_statement(n_body);
pips_debug(5, "New whileloop statement:\n");
print_statement(wl_st);
}
init | nit |
cond | ond |
incr | ncr |
body | ody |
exts | xts |
Definition at line 826 of file for_to_do_or_while_loops.c.
References CONS, copy_extensions(), empty_extensions_p(), free_extensions(), init, make_expression_statement(), make_sequence(), make_statement_from_statement_varargs_list(), make_whileloop_statement(), NIL, pips_debug, sequence_undefined, STATEMENT, statement_extensions, and STATEMENT_NUMBER_UNDEFINED.
Referenced by controlize_forloop(), transform_a_for_loop_into_a_while_loop(), and transform_a_for_loop_statement_into_a_while_loop().
void full_control_graph | ( | string | name | ) |
FULL CONTROL GRAPH for module NAME.
should put something in the db if made as a pass
name | ame |
Definition at line 259 of file graph.c.
References build_full_ctrl_graph(), and db_get_memory_resource().
void fuse_sequences_in_unstructured | ( | statement | s | ) |
Try to transform each control sequence in a single statement instead of a list of control nodes:
The entry point of the unstructured:
and its exit point:
To store the list of the controls to fuse we use a mapping since we need to keep track of eventual previous fuse on a control:
print_statement(s);
Select a node with only one successor:
Since I use an O(n) algorithm instead of an O(n^2) all this condition must be checked again later since these topological and semantical properties may have changed during the fusion phase. I think it is true because the fused graph is included into the former graph but I am too lazy to write a proof... :-( Have a look to Validation/Control/create.f.
...Accept the exit node
Ok, we have found a node in a sequence. Note that we cannot fuse with the entry node since it must keep this role...
But if c is empty, we can fuse it with any successor without changing the semantincs, even if the successor is the entry node. Don't do this if there is a comment since it mess up the original source look-alike.
The fact we can have a cycle is considered a page below...
Put the control in the fuse list. Since no fusing occurs yet, the address of a control node is itself:
Use also a real list to remove the non-determinism of a later HASH_MAP. Note that since it follow a depth-first algorithm, the output program is more likely to be similar to the output, especially with cycles in the control graph:
Reverse the list to follow the order of appearance :
Now, since we have the list of the control nodes to fuse with their successors, do the fusion:
Find the address of a control node to fuse even if it has already been fused with predecessors through a transitive closure:
...The control node has not been moved
...or it has not been moved because it is not a control node to fuse anyway.
Ok, the node has been located:
Follow a former control movement:
fprintf(stderr,"Statement with label \"s" for control a_control_fo_fuse=p
",
entity_local_name(statement_label(control_statement(a_control_to_fuse))),
a_control_to_fuse);
print_statement(control_statement(a_control_to_fuse));
fprintf(stderr,"Let's print the statement a second time to see its label again:\n");
print_statement(control_statement(a_control_to_fuse));
}
pips_debug(5, "All the unstructured %p:\n", u);
print_statement(s);
}
Verify that the fusion is still valid:
...Accept the exit node
||entity_empty_label_p(statement_to_label(control_statement(the_successor)))
Well, it seems to be a real sequence, at most a loop with 2 control nodes...
make st with the statements of 2 following nodes:
Update the entry node if we fuse with it:
If the node "the_successor" is in the fuse list, we want to keep track of its new place, that is in fact fused in "a_control_to_fuse", so that an eventual fusion will use "a_control_to_fuse" instead of "the_successor":
Ok, "the_successor" is a node to fuse or that has been already fused (in this case the following is useless, but anyway...). Thus we keep track of its new location:
Update the potentially modified entry and exit nodes:
Definition at line 250 of file unspaghettify.c.
References CAR, CONS, CONTROL, control_consistent_p(), CONTROL_MAP, control_predecessors, control_statement, control_successors, empty_statement_or_continue_p(), empty_statement_or_continue_without_comment_p(), fprintf(), fuse_2_control_nodes(), gen_free_list(), gen_in_list_p(), gen_length(), gen_nreverse(), get_bool_property(), hash_defined_p(), hash_get(), hash_pointer, hash_put(), hash_table_free(), hash_table_make(), hash_update(), ifdebug, instruction_unstructured, MAP, NIL, pips_assert, pips_debug, print_arguments(), statement_instruction, statement_to_implicit_target_labels(), statement_to_label(), unstructured_consistent_p(), unstructured_control, and unstructured_exit.
Referenced by recursively_restructure_an_unstructured().
controlmap get_ctrl_graph | ( | void | ) |
bool guess_late_read_effect_on_entity | ( | expression | init, |
entity | loop_index | ||
) |
Assuming loop_index is a potential do loop index, and init a comma expression, do we have subexpressions after the loop_index initialization that may use this index? If yes, the loop cannot be transformed into a DO loop, because this subexpression will be moved before the loop index initialization. Or the loop index initialization should be replicated before the loop.
Example (SPEC2006, milc):
for (i = parity==0x01?even_sites_on_node:0, s = &lattice[i]; i<(parity==0x02?even_sites_on_node:sites_on_node); i++, s++) {
s = &lattice[i] is going to be placed ahead of i's own initialization.
In other words, the loop can be changed in different ways:
init | nit |
loop_index | oop_index |
Definition at line 412 of file for_to_do_or_while_loops.c.
References call_arguments, call_function, ENTITY_COMMA_P, EXPRESSION, expression_call(), expression_call_p(), expression_to_reference_list(), f(), FOREACH, gen_free_list(), guess_write_effect_on_entity(), init, loop_index, NIL, REFERENCE, and reference_variable.
Referenced by for_to_do_loop_conversion().
void init_ctrl_graph | ( | void | ) |
initializations
no loop back
Definition at line 315 of file graph.c.
References push_successors(), and travel_decision.
Referenced by handle_independent_directive(), handle_reduction_directive(), and propagate_synonym().
void init_reachable | ( | statement | start | ) |
start | statement. |
start | tart |
Definition at line 223 of file unreachable.c.
References debug_off, debug_on, propagate(), and start.
Referenced by module_name_to_preconditions(), and module_name_to_total_preconditions().
partition | artition |
Definition at line 1224 of file bourdoncle.c.
References intersect_successors_with_partition_or_complement().
Referenced by scc_to_dag().
partition | artition |
Definition at line 1230 of file bourdoncle.c.
References intersect_successors_with_partition_or_complement().
Referenced by scc_to_dag().
void intersect_successors_with_partition_or_complement | ( | control | c, |
list | partition, | ||
bool | complement_p | ||
) |
If complement_p, preserve successors in the complement of partition.
Else preserve successors in partition. Take care of test nodes wich must keep two successors no matter what.
The CFG may not be connexe or the exit path may be hidden by a STOP statement
Let's boldy assume the parent control node is used as a CFG test statement and preserve the number of successors.
It is not a CFG test node: get rid of useless
Not true: you may have non-connexe CFG and loops with no exit.
pips_assert("We still have at least one successor", gen_length(*succs)>0);
partition | artition |
complement_p | omplement_p |
Definition at line 1181 of file bourdoncle.c.
References CAR, CONS, CONTROL, CONTROL_, control_successors, control_test_p(), gen_in_list_p(), gen_length(), gen_list_and(), gen_list_and_not(), make_meaningless_control(), MAPL, NIL, and pips_assert.
Referenced by intersect_successors_with_partition(), and intersect_successors_with_partition_complement().
Referenced by add_arrow_in_ctrl_graph(), and push_successors().
Definition at line 154 of file bourdoncle.c.
References control_statement, and statement_undefined_p.
Referenced by add_test_successor(), check_control_statement(), clean_up_control_test(), clean_up_embedding_graph(), control_cons_compare(), control_test_p(), cycle_to_flow_sensitive_preconditions(), dag_or_cycle_to_flow_sensitive_postconditions_or_transformers(), dag_to_flow_sensitive_preconditions(), davinci_print_control_node(), davinci_print_non_deterministic_unstructured(), entry_or_exit_control_p(), get_control_precondition(), node_to_path_transformer_or_postcondition(), one_successor_kind_only_p(), print_embedding_graph(), process_ready_node(), process_unreachable_node(), registered_controls_p(), replicate_cycles(), store_control_fix_point(), store_control_postcondition(), unstructured_to_effects(), update_control_postcondition(), and update_partition().
bool new_controlizer | ( | const char * | module_name | ) |
module.c
module.c
Interface for pipsdbm and pipsmake
Should never happen
To have the debug in unspaghettify_statement() working:
The statement of a compilation unit is a long list of continue statements and it takes a long time to restructure although nothing is done in the end. So, let's skip this useless processing. SG:it may be ok to skip it, but we still need to call module_reorder ...
By setting this property, we try to unspaghettify the control graph of the module:
With C code, some local declarations may have been lost by the (current) restructurer. FI: not investigated; should be useless by now..
Reorder the module, because we have a new statement structure.
module_name | odule_name |
Definition at line 102 of file module.c.
References c_module_p(), code_language, compilation_unit_p(), controlizer(), copy_statement(), db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, entity_initial, entity_undefined_p, forloop_domain, gen_recurse, gen_true(), get_bool_property(), hcfg(), ifdebug, is_language_fortran, language_tag, module_name(), module_name_to_entity(), module_reorder(), pips_assert, pips_user_warning, reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), set_prettyprint_language_from_property(), statement_consistent_p(), statement_domain, transform_a_for_loop_statement_into_a_while_loop(), try_to_transform_a_for_loop_into_a_do_loop(), unspaghettify_statement(), update_unstructured_declarations(), USE_OLD_CONTROLIZER_ENV_VAR_NAME, value_code, and value_code_p.
Referenced by controlizer().
ps | s |
Definition at line 325 of file graph.c.
References push_successors(), and travel_decision.
Referenced by handle_independent_directive(), handle_reduction_directive(), and propagate_synonym().
useful for non-deterministic control flow graph only
There exists at least one real successor of the requested kind and only meaningless successors of the other kind.
true_p | rue_p |
Definition at line 2451 of file bourdoncle.c.
References CONTROL, control_successors, control_test_p(), MAP, meaningless_control_p(), and pips_assert.
Referenced by false_successors_only_p(), and true_successors_only_p().
unstructured partition_to_unstructured | ( | control | vertex, |
list | partition | ||
) |
Build a new unstructured (CFG) for partition.
vertex is the entry and exit point. New nodes must be allocated because the parent graph is untouched. vertex is supposed to be included into partition.
Create the translation table replicate_map
Generate new unstructured with relevant entry and exit node vertex
Update arcs
Update predecessors
The only predecessors that are useful are in partition
This predecessor is irrelevant
Handle successors
This successor is irrelevant but irrelevant true branches must be preserved
A second irrelevant successor is not needed. But are we ready to have IF nodes with only one successor?
useless = CONS(CONTROL, old_c, useless);
vertex | ertex |
partition | artition |
Definition at line 1053 of file bourdoncle.c.
References CAR, CDR, CONS, CONTROL, CONTROL_, control_predecessors, control_shallow_copy(), control_successors, control_to_replicate(), control_undefined, control_undefined_p, gen_free_list(), gen_in_list_p(), gen_length(), gen_list_and_not(), hash_get(), hash_pointer, hash_table_free(), hash_table_make(), hash_table_undefined, HASH_UNDEFINED_VALUE, make_meaningless_control(), make_unstructured(), MAP, MAPL, NIL, pips_assert, replicate_map, unstructured_undefined, and useless().
bool proper_cycle_head_p | ( | control | c, |
hash_table | scc_map | ||
) |
This node is really the head of a cycle (red on daVinci pictures).
scc_map | cc_map |
Definition at line 2405 of file bourdoncle.c.
References HASH_MAP, and unstructured_control.
Referenced by replicate_cycles().
unstructured proper_cycle_head_to_scc | ( | control | h, |
hash_table | scc_map | ||
) |
Retrieve a scc_u from its head.
scc_map | cc_map |
Definition at line 2368 of file bourdoncle.c.
References HASH_MAP, unstructured_control, and unstructured_undefined.
Referenced by dag_to_flow_sensitive_preconditions().
void reset_ctrl_graph | ( | void | ) |
Try to simplify the control graph of a module by removing useless CONTINUEs, unreachable code, etc.
as in unspaghettify.
Do also test restructuring and control graph recursive graph decomposition.
Get the true resource, not a copy.
Reorder the module, because new statements may have been changed.
mod_name | od_name |
Definition at line 1492 of file unspaghettify.c.
References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, local_name_to_top_level_entity(), module_reorder(), reset_current_module_entity(), reset_current_module_statement(), restructure_statement(), set_current_module_entity(), set_current_module_statement(), and strdup().
void restructure_statement | ( | statement | mod_stmt | ) |
The real entry point of control graph restructuring:
mod_stmt | od_stmt |
Definition at line 1477 of file unspaghettify.c.
References currently_apply_recursive_decomposition, currently_apply_test_restructuring, and unspaghettify_or_restructure_statement().
Referenced by restructure_control().
void set_ctrl_graph | ( | controlmap | ) |
void simple_restructure_statement | ( | statement | mod_stmt | ) |
A simple cleaning of the control graph without major topological restructuring.
Used by example by PHRASE.
mod_stmt | od_stmt |
Definition at line 1435 of file unspaghettify.c.
References currently_apply_recursive_decomposition, currently_apply_test_restructuring, and unspaghettify_or_restructure_statement().
Referenced by full_spaghettify(), identify_statements_to_distribute(), and safescale_distributor().
Test if the execution goes on after the given statement.
For example it is false after a "return" in C
Definition at line 242 of file unreachable.c.
References continued_p.
Test if the given statement is reachable from some statements given at init_reachable(start)
Definition at line 234 of file unreachable.c.
References reached_p.
Referenced by statement_to_postcondition(), and statement_to_total_precondition().
Extract the statement from an exit node of an unstructured statement if it is a useful statement.
s | is the statement that contains an unstructured |
The exit node is the landing pad of the control graph. But if it is not a continue, that means that its statement is a useful instruction at the end of the unstructured and we can take it out of the unstructured. We just return the statement directly containing the unstructured.
Right now, it does not extract a RETURN since as explained in ᅵ PIPS: Internal Representation of Fortran and C Code ᅵ about RETURN_LABEL_NAME in the Entities section, since a RETURN with a label at the exit of un unstructured is always the representation of a RETURN in Fortran unstructured code... So even for C code, a return stay inside an unstructured. RK does not think it is important anyway...
To return and keep track of the unstructured:
pips_debug(5,
"Statement at entry:\n");
print_statement(s);
}
First, linearize the exit statement since fuse_sequences_in_unstructured() may have gathered many statements in a messy way:
Then normalize to have only one non-sequence statement as the exit node:
Well, this should be always true if the sequence survived to clean_up_sequences_rewrite()...
Then, append the last statements at the end of the unstructured:
...followed by the last statements:
Fix the variables for the following pass:
Here the_exit_statement is not a sequence.
Put an empty exit node and keep the statement for the label:
Replace the unstructured by an unstructured followed by the out-keeped instruction:
Keep track of the statement number:
Heavily rely on a later clean_up_sequences to normalize the above...
Definition at line 734 of file unspaghettify.c.
References CAR, CDR, clean_up_sequences_internal(), CONS, control_statement, empty_statement_or_continue_p(), gen_free_list(), gen_length(), ifdebug, instruction_sequence, instruction_sequence_p, instruction_to_statement(), instruction_unstructured, instruction_unstructured_p, make_continue_instruction(), make_instruction_block(), NIL, nop_statement_p(), pips_assert, return_statement_p(), sequence_statements, STATEMENT, statement_consistent_p(), statement_instruction, statement_number, and unstructured_exit.
Referenced by recursively_restructure_an_unstructured().
void transform_a_for_loop_into_a_while_loop | ( | forloop | f | ) |
Try to to transform the C-like for-loops into Fortran-like do-loops.
Assume we are in a gen_recurse since we use gen_get_recurse_ancestor(f).
The forloop is freed and replaced by a while loop in the statement owning the for-loop
Get the instruction owning the forloop:
Get the statement owning instruction owning the forloop:
Get a sequence with a while-loop instead:
These fields have been re-used, so protect them from memory recycling:
We need to replace the for-loop instruction by the sequence instruction. The cleaner way should be to delete the first one and make the other one, but since we are in a gen_recurse() and we iterate on the first one, it is dangerous. Well, I've tried and it works, but valgrind complains a bit. :-)
So change the type of the instruction on the fly instead:
And discard the old for:
Since we have replaced a statement that may have comments and labels by a sequence, do not forget to forward them where they can be:
FI: one issue: st is an ancestor of the current object and some of its pointers are going to be modified although they are being processed by gen_recurse()...
Removed useless instructions that may remain:
print_statement(st);
pips_debug(5, "Exiting with statement\n");
}
Definition at line 876 of file for_to_do_or_while_loops.c.
References clean_up_sequences(), expression_undefined, f(), fix_sequence_statement_attributes(), for_to_while_loop_conversion(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_forloop(), gen_get_recurse_ancestor(), instruction_sequence, instruction_tag, is_instruction_sequence, pips_debug, statement_extensions, and statement_undefined.
void transform_a_for_loop_statement_into_a_while_loop | ( | statement | st | ) |
Same as above, but with no calls to ancestors.
Get the instruction owning the forloop:
Get the statement owning instruction owning the forloop:
Get a sequence with a while-loop instead:
These fields have been re-used, so protect them from memory recycling:
We need to replace the for-loop instruction by the sequence instruction. The cleaner way should be to delete the first one and make the other one, but since we are in a gen_recurse() and we iterate on the first one, it is dangerous. Well, I've tried and it works, but valgrind complains a bit. :-)
So change the type of the instruction on the fly instead:
And discard the old for:
Since we have replaced a statement that may have comments and labels by a sequence, do not forget to forward them where they can be:
FI: one issue: st is an ancestor of the current object and some of its pointers are going to be modified although they are being processed by gen_recurse()...
Removed useless instructions that may remain:
print_statement(st);
pips_debug(5, "Exiting with statement\n");
}
st | t |
Definition at line 928 of file for_to_do_or_while_loops.c.
References clean_up_sequences(), expression_undefined, f(), fix_sequence_statement_attributes(), for_to_while_loop_conversion(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, forloop_statement_p(), free_forloop(), instruction_forloop, instruction_sequence, instruction_tag, is_instruction_sequence, pips_debug, statement_extensions, statement_instruction, and statement_undefined.
Referenced by for_loop_to_while_loop(), and new_controlizer().
Definition at line 2474 of file bourdoncle.c.
References one_successor_kind_only_p().
Referenced by dag_to_flow_sensitive_preconditions(), and process_ready_node().
void try_to_transform_a_for_loop_into_a_do_loop | ( | forloop | f | ) |
Try to to transform the C-like for-loops into Fortran-like do-loops.
Assume we are in a gen_recurse since we use gen_get_recurse_ancestor(f).
Get the englobing statement of the "for" assuming we are called from a gen_recurse()-like function:
Definition at line 740 of file for_to_do_or_while_loops.c.
References expression_undefined, f(), for_to_do_loop_conversion(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_forloop(), gen_get_recurse_ancestor(), make_instruction_sequence(), pips_debug, sequence_undefined_p, statement_instruction, and statement_undefined.
Referenced by for_loop_to_do_loop(), and new_controlizer().
Try to simplify the control graph of a module by removing useless CONTINUEs, unreachable code.
Try to structure a little bit more and so on according to some properties.
Unspaguettify is now targetted to be included in the controlizer.
Get the true resource, not a copy.
Reorder the module, because new statements may have been changed.
mod_name | od_name |
Definition at line 1450 of file unspaghettify.c.
References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, local_name_to_top_level_entity(), module_reorder(), reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), strdup(), and unspaghettify_statement().
void unspaghettify_or_restructure_statement | ( | statement | mod_stmt | ) |
The entry point common to unspaghettify or restructure a module:
Track the number of restructurations done for a fix point:
To track the number of restructuring iterations:
pips_debug(5, "Statement before unspaghettify_or_restructure_statement:\n");
print_statement(mod_stmt);
}
Split the recursion in three parts to fit in my brain:
First, clean up easy things done by the controlizer:
Then try to hierarchize the control flow:
Now apply some local rule, such as if/then/else restructuring and so on:
End by removing parasitic sequences:
If something changed, retry further restructuring:
pips_debug(5, "Statement after unspaghettify_or_restructure_statement:\n");
print_statement(mod_stmt);
}
mod_stmt | od_stmt |
Definition at line 1330 of file unspaghettify.c.
References clean_up_control(), clean_up_sequences(), control_graph_recursive_decomposition(), currently_apply_recursive_decomposition, debug_off, debug_on, display_unspaghettify_statistics(), gen_recurse, gen_true(), get_bool_property(), ifdebug, initialize_unspaghettify_statistics(), N_ITER_RESTRUCTURE_FIX_POINT, pips_assert, pips_debug, pips_user_warning, put_formats_at_module_beginning(), put_formats_at_module_end(), recover_structured_while(), recursively_restructure_an_unstructured(), statement_consistent_p(), statement_domain, total_number_of_restructurations(), and unstructured_domain.
Referenced by restructure_statement(), simple_restructure_statement(), and unspaghettify_statement().
void unspaghettify_statement | ( | statement | mod_stmt | ) |
The real entry point of unspaghettify:
mod_stmt | od_stmt |
Definition at line 1421 of file unspaghettify.c.
References currently_apply_recursive_decomposition, currently_apply_test_restructuring, get_bool_property(), STUB_ERROR, and unspaghettify_or_restructure_statement().
Referenced by controlizer(), copy_value_of_write(), copy_value_of_write_with_cumulated_regions(), mpi_conversion(), new_controlizer(), ProcessEntry(), and unspaghettify().
bool unstructured_consistency_p | ( | unstructured | u, |
bool | assert_p | ||
) |
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.
assert_p | ssert_p |
Definition at line 52 of file cfg.c.
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().
unstructured unstructured_shallow_copy | ( | unstructured | u, |
hash_table | ancestor_map | ||
) |
Do not go down into nested unstructured and replicate all control nodes
Update predecessor and successor arcs of the new control nodes to point to the new control nodes using the global conversion mapping replicate_map
Generate new unstructured with relevant entry and exit nodes
Generate ancestor_map as the inverse function of replicate_map
ancestor_map | ncestor_map |
Definition at line 1009 of file bourdoncle.c.
References add_child_parent_pair(), control_domain, control_shallow_copy(), control_to_replicate(), control_translate_arcs(), gen_false(), gen_multi_recurse(), gen_null(), gen_true(), HASH_MAP, hash_pointer, hash_table_free(), hash_table_make(), hash_table_undefined, hash_table_undefined_p, ifdebug, make_unstructured(), pips_assert, print_replicate_map(), replicate_map, statement_domain, unstructured_control, unstructured_exit, and unstructured_undefined.
Referenced by bourdoncle_partition(), and replicate_cycles().
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.
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().
|
extern |
|
extern |
Definition at line 29 of file old_controlizer.c.
|
extern |