PIPS
|
Go to the source code of this file.
Macros | |
#define | MEM_TO_TMP_SIZE 100 |
– atomizer.c More... | |
#define | MEM_VAR 1 |
Useful for atomizer_of_expression(). More... | |
#define | NO_MEM_VAR 0 |
Functions | |
static void | initialize_global_variables (char *mod_name) |
=========================================================================== More... | |
static void | reset_global_variables () |
static entity | build_new_variable (entity module, basic b) |
static bool | indirection_test (reference ref, expression expr) |
void | normalize_wp65_code (statement stat) |
static void | rm_db_block (statement stat) |
static statement | rm_block_block_statement (statement stat) |
bool | atomizer (const string mod_name) |
=========================================================================== More... | |
void | atomizer_of_unstructured (u) |
=========================================================================== More... | |
void | atomizer_of_statement (statement stmt, Block *cb) |
=========================================================================== More... | |
void | atomizer_of_block (instruction i) |
=========================================================================== More... | |
void | atomizer_of_test (test t, Block *cb) |
=========================================================================== More... | |
void | atomizer_of_loop (loop l, Block *cb) |
=========================================================================== More... | |
void | atomizer_of_call (call c, Block *cb) |
=========================================================================== More... | |
void | atomizer_of_intrinsic (call c, Block *cb) |
=========================================================================== More... | |
void | atomizer_of_external (call c, Block *cb) |
=========================================================================== More... | |
list | atomizer_of_expressions (list expl, Block *cb) |
=========================================================================== More... | |
expression | atomizer_of_expression (expression exp, Block *cb, int mem_var) |
=========================================================================== More... | |
void | atomizer_of_array_indices (expression exp, Block *cb) |
=========================================================================== More... | |
Variables | |
list | l_inst = list_undefined |
FI: the following global variables are not declared STATIC because they also are used in codegen.c. More... | |
hash_table | MemToTmp = hash_table_undefined |
These lists memorize all the new created entities of each type. More... | |
static graph | mod_dg = graph_undefined |
Dependence graph of the current module. More... | |
#define MEM_TO_TMP_SIZE 100 |
– atomizer.c
These functions produce atomic instructions.
An atomic instruction is an instruction that whether, loads a variable into a temporary variable, stores a variable from a temporary variable or computes numericals operations upon temporary variables.
The scalar variables have a special treatment. Indeed, these variables are loaded in temporaries and kept in them while they are used or defined. It is only when they are no more used that they are stored back. This treatment is done with the dependence graph.
Note : in the following, we'll distinguish two kinds of variables: the memory variables and the temporary variables. The firsts will be called variables, the latter temporaries. The temporaries should not appear in the dependence graph; ie. that there can not be any dependences upon the temporaries. The temporaries can also be called registers.
This phase produces variables and temporaries. The variables produced are prefixed : "AUX". The temporaries produced are prefixed : "TMP". Another kind of entities can be encounter, the NLCs. They have the same status as the temporaries, ie. they should not appear in the dependence graph. More, they have another property : an expression that contains only NLCs and is integer linear, is not decomposed by the atomizer, ie. it is considered as a constant. Gives the size of the hash table named "MemToTmp".
Definition at line 64 of file atomizer.c.
#define MEM_VAR 1 |
Useful for atomizer_of_expression().
It tells if the function can return a variable (MEM_VAR) or if it must return a temporary.
Definition at line 69 of file atomizer.c.
#define NO_MEM_VAR 0 |
Definition at line 70 of file atomizer.c.
===========================================================================
void atomizer(const char* module_name): computes the translation of Fortran instructions into Three Adresses Code instructions.
This translation is done after two pre-computations : _ The first one puts all the integer linear expressions into a normal pattern (see norm_exp.c). _ The second one removes all the defs with no def-use dependence.
Also, after the atomization, the module statement is reordered, and declarations are made for the new variables and temporaries.
The atomization uses the CODE, CUMULATED_EFFECTS and DG (dependence graph) resources.
Called functions: _ module_body_reorder() : control/control.c
COMPUTATION
All the expressions are put into a normal pattern : the NLCs in the innermost parenthesis.
All the defs with no def-use dependence are removed.
Module is atomized.
We reorder the module. It is necessary because new statements have been generated. The reordering will permit to reuse the generated code for further analysis.
We declare the new variables and the new temporaries.
insert_new_declarations(mod_name);
We save the new CODE.
mod_name | od_name |
Definition at line 226 of file atomizer.c.
References atomizer_of_statement(), db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, defs_elim_of_statement(), discard_module_declaration_text(), get_bool_property(), get_debug_level(), initialize_global_variables(), local_name_to_top_level_entity(), mod_dg, mod_stat, module, module_reorder(), normal_expression_of_statement(), normalize_wp65_code(), pips_user_warning, reset_cumulated_rw_effects(), reset_current_module_entity(), reset_current_module_statement(), reset_global_variables(), rm_block_block_statement(), set_cumulated_rw_effects(), set_current_module_entity(), set_current_module_statement(), strdup(), and user_log().
void atomizer_of_array_indices | ( | expression | exp, |
Block * | cb | ||
) |
===========================================================================
void atomizer_of_array_indices(expression exp, Block *cb): Applies the translation on an array expression.
Only the indices of the array are translated, in order to have a list of temporary variables.
We translate all the indices expressions.
exp | xp |
cb | b |
Definition at line 932 of file atomizer.c.
References atomizer_of_expressions(), exp, expression_syntax, expression_to_string(), pips_debug, reference_indices, and syntax_reference.
Referenced by atomizer_of_expression().
void atomizer_of_block | ( | instruction | i | ) |
===========================================================================
void atomizer_of_block(instruction inst): Applies the translation on all the statements of the block of the instruction given in argument.
Note: the "instruction_tag" of "inst" must be a block, otherwise, it's a user error.
We enter a new block of statements, so we generate a new variable of type "Block". "last" representes the list of statements not translated yet. "first" representes the list of statements that are translated, plus the statements that were generated by them. The statement being translated (current statement) is the first of the "last" list. When the translation of a statement is done, it is put at the end of the "first" list.
Nothing to do!!
Initialization of the new "Block".
"cb->last" is the list of the statements not yet visited
Gets the current statement.
This current statement has not yet generated another statement.
Translation of the current statement.
The current statement is put at the end of the "first" list.
Since there could have been creations of statements in the list "cb->first" we have to update the block of the instruction.
Memory deallocation
Definition at line 473 of file atomizer.c.
References atomizer_of_statement(), CAR, CDR, CONS, debug(), Block::first, free(), gen_nconc(), instruction_block, instruction_tag, is_instruction_block, Block::last, malloc(), NIL, STATEMENT, Block::stmt_generated, and user_error.
Referenced by atomizer_of_statement().
===========================================================================
void atomizer_of_call(call c, Block *cb): Applies the translation on an instruction call.
The two main kinds of call are: _ external call, ie user_defined function or subroutine. _ intrinsic call.
The variable "cb" memorises the information about the block of statements that contains the call statement.
Evite d'atomiser un parame`tre inexistant ( :-) ) d'un intrinsic sans argument, du style * dans : write ... FMT=*... RK, 24/02/1994.
cb | b |
Definition at line 660 of file atomizer.c.
References atomizer_of_external(), atomizer_of_intrinsic(), call_arguments, call_function, entity_initial, entity_name, is_value_code, is_value_constant, is_value_intrinsic, is_value_symbolic, is_value_unknown, NIL, pips_internal_error, and value_tag.
Referenced by atomizer_of_expression(), and atomizer_of_statement().
expression atomizer_of_expression | ( | expression | exp, |
Block * | cb, | ||
int | mem_var | ||
) |
===========================================================================
expression atomizer_of_expression(expression exp, Block *cb, int mem_var): Applies the translation on an expression.
It consists in assigning a new temporary variable to the expression, while the sub-expressions that it may contain are recursively translated.
If "exp" is only composed of NLCs variables (eventually a constant term), then the expression is treated like a constant, ie unchanged. NLC means Normalized Loop Counter.
The translation of expressions that reference a variable is not done only if the flag "mem_var" has the value "MEM_VAR". Otherwise, the variable is assigned to a temporary variable. The function "atomizer_of_array_indices()" translates the list of indices (when not empty) of the variable given in argument. Note: a scalar variable is an array with an empty list of indices.
The variable "cb" memorises the information about the block of statements that contains the expression.
An expression that is integer linear and is exclusively composed of NLCs is considered like a constant, ie not translated.
Two cases : _ a "real" call, ie an intrinsic or external function _ a constant
Evite d'atomiser un parame`tre inexistant ( :-) ) d'un intrinsic sans argument, du style * dans : write ... FMT=*... RK, 24/02/1994.
Translates the arguments of the call.
Generates the assign statement, and put it into the current block.
Constant value.
exp | xp |
cb | b |
mem_var | em_var |
Definition at line 849 of file atomizer.c.
References assign_tmp_to_exp(), atomizer_of_array_indices(), atomizer_of_call(), call_arguments, call_constant_p, call_function, debug(), entity_initial, exp, expression_syntax, expression_to_string(), expression_undefined, is_syntax_call, is_syntax_range, is_syntax_reference, MEM_VAR, NIL, nlc_linear_expression_p(), pips_debug, pips_internal_error, syntax_call, syntax_tag, and value_intrinsic_p.
Referenced by atomizer_of_expressions(), atomizer_of_external(), atomizer_of_intrinsic(), atomizer_of_loop(), and atomizer_of_test().
===========================================================================
list atomizer_of_expressions(list expl, Block *cb): Applies the translation on a list of expressions.
The variable "cb" memorises the information about the block of statements that contains the expressions.
Returns a list of expressions containing the translated expressions.
expl | xpl |
cb | b |
Definition at line 811 of file atomizer.c.
References atomizer_of_expression(), CAR, CDR, CONS, exp, EXPRESSION, gen_nconc(), NIL, and NO_MEM_VAR.
Referenced by atomizer_of_array_indices(), atomizer_of_external(), atomizer_of_intrinsic(), and atomizer_of_test().
===========================================================================
void atomizer_of_external(call c, block *cb): Translates the arguments of the call to an external function.
In fact, these arguments are kept as memory variable. When, the argument is an expression containing a "call" (a real call to a function and not a call to a constant), this expression is assigned to a new auxiliary variable which takes its place in the list of arguments. It is a variable, not a temporary (see the introduction at the beginning of this file).
Called functions : _ make_entity_expression() : ri-util/util.c _ make_assign_statement() : ri-util/statement.c
All the argument expressions are scanned. If an expression is not a reference (then, it is a call), we create an auxiliary variable. The expression is assigned to this new variable which is given in argument to the function, instead of the expression. If it is a reference, the corresponfding key (if it exists) in the hash table MemToTmp is deleted.
cb | b |
Definition at line 753 of file atomizer.c.
References atomizer_of_expression(), atomizer_of_expressions(), aux, AUX_ENT, basic_of_expression(), call_arguments, call_constant_p, CAR, CDR, CONS, EXPRESSION, expression_syntax, gen_nconc(), hash_del(), is_syntax_reference, make_assign_statement(), make_entity_expression(), make_new_entity(), MEM_VAR, MemToTmp, NIL, put_stmt_in_Block(), reference_indices, reference_variable, syntax_call, syntax_reference, and syntax_tag.
Referenced by atomizer_of_call().
===========================================================================
void atomizer_of_intrinsic(call c, block *cb): translates the arguments of the intrinsic function. It treats two cases: assign call, and others.
Assign calls are treated differently because the first argument is the left-hand-side, so this argument is translated with the MEM_VAR option.
Assign expressions.
If the rhs expression is integer linear and exclusively composed of NLC variables, it is considered like a constant, ie not translated. Otherwise, it is translated normaly.
Translation of the lhs expression. We keep the memory variable.
The lhs variable is stored, so it is delete from MemToTmp.
The call is not an assignment, then each arguments is translated.
cb | b |
Definition at line 699 of file atomizer.c.
References atomizer_of_expression(), atomizer_of_expressions(), call_arguments, call_function, CAR, CDR, CONS, ENTITY_ASSIGN_P, EXPRESSION, expression_syntax, expression_to_string(), hash_del(), MEM_VAR, MemToTmp, NIL, nlc_linear_expression_p(), NO_MEM_VAR, pips_debug, reference_variable, and syntax_reference.
Referenced by atomizer_of_call().
===========================================================================
void atomizer_of_loop(loop l, Block *cb): Applies the translation on an instruction loop.
All written variables of the loop are removed from MemToTmp.
The variable "cb" memorizes the information about the block of statements that contains the loop statement.
Called functions: _ entity_scalar_p() : ri-util/entity.c _ make_block_with_stmt() : loop_normalize/utils.c
We have to remove from MemToTmp all the (scalars) variables that are written in this loop.
Translation of the three expressions of the loop range.
Afterwards, the body statement of the loop is translated. If this statement is not a block of statements, then it is put inside one (the resulting block contains only one statement !!).
cb | b |
Definition at line 603 of file atomizer.c.
References action_tag, atomizer_of_expression(), atomizer_of_statement(), CAR, CDR, debug(), EFFECT, effect_action, effect_any_reference, entity_local_name(), entity_scalar_p(), hash_del(), is_action_write, Block::last, load_rw_effects_list(), loop_body, loop_index, loop_range, make_block_with_stmt_if_not_already(), MemToTmp, NIL, NO_MEM_VAR, range_increment, range_lower, range_upper, reference_variable, and STATEMENT.
Referenced by atomizer_of_statement().
===========================================================================
void atomizer_of_statement(statement stmt, Block *cb): computes the translation from Fortran to Three Addresses Code (ATOMIZER) of a statement ("stmt").
This function can be called in two different cases: _ If "cb" is NULL, then "stmt" is taken from a control C of the control graph. In such case, we have to find out where is the block in which we'll put the statements created by the translation of "stmt". . if "stmt" is a block, then this is it. . else, it is the predecessor of C. This control is obtained by the function find_control_block(). _ Else, "stmt" is one of the statements of a block, its creations are put in this block.
The "cb" variable refers to the current block of statements where "stmt" is.
Initialisation of "cb", if it is a NULL pointer.
The control in which the created statements are put is not the same as the control of "stmt".
We get the control in which we'll put our new statements.
We create the structure that will keep the created statements during the computation, before putting them in the control "c".
Computation of "stmt".
Updates of the control graph, if the generated statements are not put in the same control as "stmt".
The created statements are put in the control just before the control of the statement that created them.
Memory deallocation
stmt | tmt |
cb | b |
Definition at line 381 of file atomizer.c.
References atomizer_of_block(), atomizer_of_call(), atomizer_of_loop(), atomizer_of_test(), atomizer_of_unstructured(), CONS, control_statement, control_undefined, debug(), find_control_block(), Block::first, free(), instruction_block, instruction_call, instruction_loop, instruction_tag, instruction_test, instruction_unstructured, is_instruction_block, is_instruction_call, is_instruction_goto, is_instruction_loop, is_instruction_test, is_instruction_unstructured, Block::last, malloc(), NIL, pips_internal_error, STATEMENT, statement_instruction, Block::stmt_generated, and user_error.
Referenced by atomizer(), atomizer_of_block(), atomizer_of_loop(), atomizer_of_test(), and atomizer_of_unstructured().
===========================================================================
void atomizer_of_test(test t, Block *cb): Applies the translation on an instruction test.
It consists in translating the three arguments of the test instruction : the condition expression and the two conditional statements (true, false).
The condition argument is an expression which may contain a logical intrinsic operator : "x op y" or "op x", with "op" in (<, =, >=, etc). In such case, the tranlation does not assign a temporary for the call expression associated with the operator, it only translates the arguments of the logical operator.
The variable "cb" memorises the information about the block of statements that contains the test statement.
Called functions : _ make_block_with_stmt() : loop_normalize/utils.c
If the expression is a call to a intrinsic operation, only its arguments are translated. Note : it is not tested that the intrinsic is a logical operator. In fact, Fortran requires it.
Else, the conditional expression is translated, and the returned expression must be a temporary (NO_MEM_VAR).
Afterwards, the two conditional statements are translated. If one of these statements is not a block of statements, then it is put inside one (the resulting block contains only one statement !!).
cb | b |
Definition at line 543 of file atomizer.c.
References atomizer_of_expression(), atomizer_of_expressions(), atomizer_of_statement(), call_arguments, call_function, debug(), entity_local_name(), expression_intrinsic_operation_p(), expression_syntax, make_block_with_stmt_if_not_already(), NO_MEM_VAR, syntax_call, test_condition, test_false, and test_true.
Referenced by atomizer_of_statement().
void atomizer_of_unstructured | ( | u | ) |
===========================================================================
void atomizer_of_unstructured(unstructured u): Computes the transformation of the unstructured "u".
This unstructured contains the control graph. In the control graph, some nodes (of Newgen type "control") have a statement that is not a "block" of statements. As we need, almost always, to add new instructions before the IFs and DOs, we have to change the control graph by adding nodes : For each node V with a "control_statement" that is not a "block", we generate a node Vnew that contain a "block" with no instruction. This node Vnew has the same predecessors as V, and has V as successor; the node V keeps the same successors, but his predecessor became Vnew.
So, for each such node V, when the translation produces instructions, we need to know the corresponding Vnew, in which we put the new instructions.
That is why we use a global variable "l_inst" and a code of CONTROL_MAP with some modifications (see below). The list "l_inst" contains the instructions for which we create Vnew. The modified code of CONTROL_MAP uses a function atom_get_blocs() that creates new nodes when needed, and updates the list "l_inst".
The following code is a modification of CONTROL_MAP, from control/control.h. This code uses atom_get_blocs() which is a modification of get_blocs() (in control/control.h).
Definition at line 326 of file atomizer.c.
References atom_get_blocs(), atomizer_of_statement(), CAR, CONTROL, control_statement, debug(), find_control_block(), gen_free_list(), gen_nreverse(), hash_table_clear(), l_inst, MAPL, MemToTmp, NIL, and unstructured_control.
Referenced by atomizer_of_statement().
Definition at line 147 of file atomizer.c.
References AddEntityToDeclarations(), make_new_module_variable(), module, and pips_assert.
Referenced by normalize_wp65_code().
|
static |
Definition at line 155 of file atomizer.c.
References NORMALIZE_EXPRESSION, normalized_linear_p, pips_assert, and ref.
Referenced by normalize_wp65_code().
|
static |
===========================================================================
static void initialize_global_variables(char *mod_name) : Initializes the global variables used through out all the computation of atomizer.
set_current_module_entity(local_name_to_top_level_entity(mod_name));
The last argument says if the resource is to be modified or not :
Definition at line 105 of file atomizer.c.
References char_entities, complex_entities, db_get_memory_resource(), double_entities, hash_pointer, hash_table_make(), integer_entities, logical_entities, MEM_TO_TMP_SIZE, MemToTmp, mod_dg, NIL, real_entities, reset_rw_effects(), and set_rw_effects().
Referenced by atomizer().
void normalize_wp65_code | ( | statement | stat | ) |
reference test
function call test
test condition test
range arguments test
whileloop condition test
new variable
stat | tat |
Definition at line 161 of file atomizer.c.
References atomize_as_required(), build_new_variable(), gen_false2(), indirection_test(), and normalize_all_expressions_of().
Referenced by atomizer().
|
static |
reset_current_module_entity();
Definition at line 131 of file atomizer.c.
References char_entities, complex_entities, double_entities, graph_undefined, hash_table_undefined, integer_entities, list_undefined, logical_entities, MemToTmp, mod_dg, and real_entities.
Referenced by atomizer().
Definition at line 199 of file atomizer.c.
References gen_recurse, gen_true(), rm_db_block(), and statement_domain.
Referenced by atomizer().
|
static |
Definition at line 173 of file atomizer.c.
References CAR, CONS, fprintf(), gen_nconc(), ifdebug, instruction_block, instruction_block_p, MAPL, NIL, print_statement(), STATEMENT, and statement_instruction.
Referenced by rm_block_block_statement().
list l_inst = list_undefined |
FI: the following global variables are not declared STATIC because they also are used in codegen.c.
The list "first" is a truncated list from the first to the current statement (not included).
This global variable is used for the modification of the control graph, see commentaries of atomizer_of_unstructured() in this file.
Definition at line 79 of file atomizer.c.
Referenced by atomizer_of_unstructured(), and modify_blocks().
hash_table MemToTmp = hash_table_undefined |
These lists memorize all the new created entities of each type.
– codegen.c
They are used for the declarations of the temporaries and the auxiliaries. A hash table to map temporary variables (entities) to memory variables (entities).
Definition at line 95 of file atomizer.c.
Referenced by assign_tmp_to_exp(), atomizer_of_external(), atomizer_of_intrinsic(), atomizer_of_loop(), atomizer_of_unstructured(), find_tmp_of_exp(), initialize_global_variables(), reset_global_variables(), and store_expression().
|
static |
Dependence graph of the current module.
Definition at line 98 of file atomizer.c.
Referenced by atomizer(), initialize_global_variables(), and reset_global_variables().