ipa-cp.c (ipcp_init_stage): Calls ipa_set_called_with_variable_arg instead of setting number of formal...
2008-04-30 Martin Jambor <mjambor@suse.cz> * ipa-cp.c (ipcp_init_stage): Calls ipa_set_called_with_variable_arg instead of setting number of formal parameters to zero. (ipcp_init_stage): Do not set the number of actual parameters to zero either. (ipcp_propagate_stage): Explicitly skipping all calls to nodes which are called with variable number of arguments. (ipcp_insert_stage): Explicitely skipping all nodes which are called with variable number of arguments. (ipcp_callsite_param_print): Skipps callsites to nodes with varaible number of parameters. * ipa-prop.h (struct ipa_node_params): Added flag called_with_var_arguments (ipa_set_param_count): Added. Changed sole setter to use it. (ipa_get_param_count): Added. All readers of param_count converted to use it instead. (ipa_set_called_with_variable_arg): Added. (ipa_is_called_with_var_arguments): Added. (ipa_get_ith_param): Added. All readers of param_decls converted to use it instead. (ipa_set_cs_argument_count): Added, sole writer to argument_count changed to use it. (ipa_get_cs_argument_count): Added, all readers of argument_count changed to cal it. (ipa_get_ith_jump_func): Added. Accessors of jump values changed to use it. * ipa-prop.h (struct ipcp_formal): Renamed to ipcp_lattice (struct ipcp_lattice): Renamed cval_type to type (struct ipa_node_params): ipcp_cval renamed to ipcp_lattices * ipa-cp.c (ipcp_cval_get_cvalue): Changed return value to tree (ipcp_cval_set_cvalue): Changed type of parameter value to tree (ipcp_insert_stage): Changed the type of variable cvalue to tree (ipcp_replace_map_create): Changed the type of parameter cvalue to tree (build_const_val): Changed the type of parameter cvalue to tree (ipcp_propagate_const): Changed the type of parameter cvalue to tree (ipcp_method_cval_set_cvalue_type): Renamed parameter cval_type1 to type * ipa-prop.h (struct ipcp_formal): Replaced cvalue with tree called constant * ipa-prop.c (ipa_methodlist_init): Renamed to ipa_init_func_list (ipa_methodlist_not_empty): Removed, the sole user now checks directly (ipa_add_method): Renamed to ipa_push_func_to_list (ipa_remove_method): Renamed to ipa_pop_func_from_list (ipa_callsite_param_count): Removed. (ipa_callsite_param_count_set): Removed. (ipa_callsite_param): Removed. (ipa_callsite_callee): Removed. (ipa_callsite_compute_param): Renamed to ipa_compute_jump_functions (ipa_callsite_compute_count): Renamed to ipa_count_arguments (ipa_method_formal_count): Removed. (ipa_method_formal_count_set): Removed. (ipa_method_get_tree): Removed. (ipa_method_tree_map_create): Removed. (ipa_method_compute_tree_map): Renamed to ipa_create_param_decls_array (ipa_create_param_decls_array): Creates the array itself (ipa_create_param_decls_array): Temporary variable info instead of a few dereferences. (ipa_method_formal_compute_count): Renamed to ipa_count_formal_params (ipa_method_compute_modify): Renamed to ipa_detect_param_modifications (get_type): Removed. (ipa_jf_get_info_type): Removed. (ipa_node_create): Renamed to ipa_create_node_params (ipa_free): Renamed to ipa_free_all_node_params (ipa_nodes_create): Renamed to ipa_create_all_node_params (ipa_edges_create): Renamed to ipa_create_all_edge_args (ipa_edges_free): Renamed to ipa_free_all_edge_args (ipa_nodes_free): Integrated into ipa_free_all_node_params and removed (ipa_free_all_node_params): Deallocation to jump_functions moved to ipa_free_all_edge_args (ipa_method_tree_print): Renamed to ipa_print_all_tree_maps (ipa_method_modify_print): Renamed to ipa_print_all_params_modified (ipa_create_methodlist_node): Removed. (ipa_methodlist_method): Removed. (ipa_methodlist_method_set): Removed. (ipa_methodlist_next_method): Removed. (ipa_methodlist_next_method_set): Removed. (ipa_method_is_modified): Removed. (ipa_method_modify_create): Removed. (ipa_method_modify_init): Temporary variable info instead of a few dereferences. (ipa_detect_param_modifications): Temporary variable info instead of a few dereferences. (ipa_compute_jump_functions): Temporary variable info instead of a few dereferences. (ipa_method_modify_set): Removed. (ipa_method_tree_map): Renamed to ipa_get_param_decl_index (ipa_get_param_decl_index): Now accepts struct ipa_node_params rather than craph_node as the first parameter. (ipa_method_modify_stmt): Renamed to ipa_check_stmt_modifications (ipa_method_modify_init): Removed. (ipa_compute_jump_functions): Added a temp variable instead of repeatadly dereferencing the cgraph_edge.aux pointer (ipa_callsite_param_set_type): Removed. (ipa_compute_jump_functions): i renamed to index and moved to an inner block (ipa_callsite_param_set_info_type_formal): Removed. (ipa_callsite_param_set_info_type): Removed. (ipa_callsite_param_map_create): Removed. (ipa_callsite_tree): Removed. (ipa_callsite_caller): Removed. (ipa_pop_func_from_list): return_method removed to return_func * ipa-prop.h (enum cvalue_type): Renamed to ipa_lattice_type, prefixed all values with IPA_. Changed all users. (enum jump_func_type): Rnamed UNKNOWN_IPATYPE to IPA_UNKNOWN, CONST_IPATYPE to IPA_CONST, CONST_IPATYPE_REF to IPA_CONST_REF and FORMAL_IPATYPE IPA_PASS_THROUGH. (union parameter_info): Renamed to jump_func_value. (union jump_func_value): Renamed value to constant (struct ipa_jump_func): Renamed info_type to value (struct ipa_node): Renamed to ipa_node_params (struct ipa_node_params): Renamed ipa_arg_num to param_count (struct ipa_node_params): Renamed ipa_param_tree to param_decls (struct ipa_node_params): Renamed ipa_mod to modified_flags (struct ipa_edge): Renamed to ipa_edge_args (struct ipa_edge_args): Renamed ipa_param_num to argument_count (struct ipa_edge_args): Renamed ipa_param_map to jump_functions (struct ipa_methodlist): Renamed to ipa_func_list (struct ipa_func_list): method_p renamed to node, next_method renamed to next (ipa_methodlist_p): Removed, switched all users to struct pointer (IS_VALID_TREE_MAP_INDEX): Renamed to IS_VALID_JUMP_FUNC_INDEX From-SVN: r134818
This commit is contained in:
parent
d79967325b
commit
dcd416e3ac
294
gcc/ipa-cp.c
294
gcc/ipa-cp.c
@ -72,7 +72,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
The jump function info, ipa_jump_func, is defined in ipa_edge
|
||||
structure (defined in ipa_prop.h and pointed to by cgraph_node->aux)
|
||||
The modify info, ipa_modify, is defined in ipa_node structure
|
||||
The modify info, modified_flags, is defined in ipa_node_params structure
|
||||
(defined in ipa_prop.h and pointed to by cgraph_edge->aux).
|
||||
|
||||
-ipcp_init_stage() is the first stage driver.
|
||||
@ -89,7 +89,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
Cval of formal f will have a constant value if all callsites to this
|
||||
function have the same constant value passed to f.
|
||||
|
||||
The cval info, ipcp_formal, is defined in ipa_node structure
|
||||
The cval info, ipcp_lattice, is defined in ipa_node_params structure
|
||||
(defined in ipa_prop.h and pointed to by cgraph_edge->aux).
|
||||
|
||||
-ipcp_iterate_stage() is the second stage driver.
|
||||
@ -145,7 +145,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "tree-dump.h"
|
||||
#include "tree-inline.h"
|
||||
|
||||
/* Get orig node field of ipa_node associated with method MT. */
|
||||
/* Get orig node field of ipa_node_params associated with method MT. */
|
||||
static inline struct cgraph_node *
|
||||
ipcp_method_orig_node (struct cgraph_node *mt)
|
||||
{
|
||||
@ -173,17 +173,17 @@ static void
|
||||
ipcp_cloned_create (struct cgraph_node *orig_node,
|
||||
struct cgraph_node *new_node)
|
||||
{
|
||||
ipa_node_create (new_node);
|
||||
ipa_create_node_params (new_node);
|
||||
ipcp_method_set_orig_node (new_node, orig_node);
|
||||
ipa_method_formal_compute_count (new_node);
|
||||
ipa_method_compute_tree_map (new_node);
|
||||
ipa_count_formal_params (new_node);
|
||||
ipa_create_param_decls_array (new_node);
|
||||
}
|
||||
|
||||
/* Return cval_type field of CVAL. */
|
||||
static inline enum cvalue_type
|
||||
ipcp_cval_get_cvalue_type (struct ipcp_formal *cval)
|
||||
static inline enum ipa_lattice_type
|
||||
ipcp_cval_get_cvalue_type (struct ipcp_lattice *cval)
|
||||
{
|
||||
return cval->cval_type;
|
||||
return cval->type;
|
||||
}
|
||||
|
||||
/* Return scale for MT. */
|
||||
@ -202,32 +202,32 @@ ipcp_method_set_scale (struct cgraph_node *node, gcov_type count)
|
||||
|
||||
/* Set TYPE as cval_type field of CVAL. */
|
||||
static inline void
|
||||
ipcp_cval_set_cvalue_type (struct ipcp_formal *cval, enum cvalue_type type)
|
||||
ipcp_cval_set_cvalue_type (struct ipcp_lattice *cval, enum jump_func_type type)
|
||||
{
|
||||
cval->cval_type = type;
|
||||
cval->type = type;
|
||||
}
|
||||
|
||||
/* Return cvalue field of CVAL. */
|
||||
static inline union parameter_info *
|
||||
ipcp_cval_get_cvalue (struct ipcp_formal *cval)
|
||||
static inline tree
|
||||
ipcp_cval_get_cvalue (struct ipcp_lattice *cval)
|
||||
{
|
||||
return &(cval->cvalue);
|
||||
return cval->constant;
|
||||
}
|
||||
|
||||
/* Set VALUE as cvalue field CVAL. */
|
||||
static inline void
|
||||
ipcp_cval_set_cvalue (struct ipcp_formal *cval, union parameter_info *value,
|
||||
enum cvalue_type type)
|
||||
ipcp_cval_set_cvalue (struct ipcp_lattice *cval, tree value,
|
||||
enum ipa_lattice_type type)
|
||||
{
|
||||
if (type == CONST_VALUE || type == CONST_VALUE_REF)
|
||||
cval->cvalue.value = value->value;
|
||||
if (type == IPA_CONST_VALUE || type == IPA_CONST_VALUE_REF)
|
||||
cval->constant = value;
|
||||
}
|
||||
|
||||
/* Return whether TYPE is a constant type. */
|
||||
static bool
|
||||
ipcp_type_is_const (enum cvalue_type type)
|
||||
ipcp_type_is_const (enum ipa_lattice_type type)
|
||||
{
|
||||
if (type == CONST_VALUE || type == CONST_VALUE_REF)
|
||||
if (type == IPA_CONST_VALUE || type == IPA_CONST_VALUE_REF)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
@ -235,43 +235,43 @@ ipcp_type_is_const (enum cvalue_type type)
|
||||
|
||||
/* Return true if CONST_VAL1 and CONST_VAL2 are equal. */
|
||||
static inline bool
|
||||
ipcp_cval_equal_cvalues (union parameter_info *const_val1,
|
||||
union parameter_info *const_val2,
|
||||
enum cvalue_type type1, enum cvalue_type type2)
|
||||
ipcp_cval_equal_cvalues (tree const_val1, tree const_val2,
|
||||
enum ipa_lattice_type type1,
|
||||
enum ipa_lattice_type type2)
|
||||
{
|
||||
gcc_assert (ipcp_type_is_const (type1) && ipcp_type_is_const (type2));
|
||||
if (type1 != type2)
|
||||
return false;
|
||||
|
||||
if (operand_equal_p (const_val1->value, const_val2->value, 0))
|
||||
if (operand_equal_p (const_val1, const_val2, 0))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Compute Meet arithmetics:
|
||||
Meet (BOTTOM, x) = BOTTOM
|
||||
Meet (TOP,x) = x
|
||||
Meet (const_a,const_b) = BOTTOM, if const_a != const_b.
|
||||
Meet (IPA_BOTTOM, x) = IPA_BOTTOM
|
||||
Meet (IPA_TOP,x) = x
|
||||
Meet (const_a,const_b) = IPA_BOTTOM, if const_a != const_b.
|
||||
MEET (const_a,const_b) = const_a, if const_a == const_b.*/
|
||||
static void
|
||||
ipcp_cval_meet (struct ipcp_formal *cval, struct ipcp_formal *cval1,
|
||||
struct ipcp_formal *cval2)
|
||||
ipcp_cval_meet (struct ipcp_lattice *cval, struct ipcp_lattice *cval1,
|
||||
struct ipcp_lattice *cval2)
|
||||
{
|
||||
if (ipcp_cval_get_cvalue_type (cval1) == BOTTOM
|
||||
|| ipcp_cval_get_cvalue_type (cval2) == BOTTOM)
|
||||
if (ipcp_cval_get_cvalue_type (cval1) == IPA_BOTTOM
|
||||
|| ipcp_cval_get_cvalue_type (cval2) == IPA_BOTTOM)
|
||||
{
|
||||
ipcp_cval_set_cvalue_type (cval, BOTTOM);
|
||||
ipcp_cval_set_cvalue_type (cval, IPA_BOTTOM);
|
||||
return;
|
||||
}
|
||||
if (ipcp_cval_get_cvalue_type (cval1) == TOP)
|
||||
if (ipcp_cval_get_cvalue_type (cval1) == IPA_TOP)
|
||||
{
|
||||
ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval2));
|
||||
ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval2),
|
||||
ipcp_cval_get_cvalue_type (cval2));
|
||||
return;
|
||||
}
|
||||
if (ipcp_cval_get_cvalue_type (cval2) == TOP)
|
||||
if (ipcp_cval_get_cvalue_type (cval2) == IPA_TOP)
|
||||
{
|
||||
ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1));
|
||||
ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval1),
|
||||
@ -283,7 +283,7 @@ ipcp_cval_meet (struct ipcp_formal *cval, struct ipcp_formal *cval1,
|
||||
ipcp_cval_get_cvalue_type (cval1),
|
||||
ipcp_cval_get_cvalue_type (cval2)))
|
||||
{
|
||||
ipcp_cval_set_cvalue_type (cval, BOTTOM);
|
||||
ipcp_cval_set_cvalue_type (cval, IPA_BOTTOM);
|
||||
return;
|
||||
}
|
||||
ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1));
|
||||
@ -292,34 +292,35 @@ ipcp_cval_meet (struct ipcp_formal *cval, struct ipcp_formal *cval1,
|
||||
}
|
||||
|
||||
/* Return cval structure for the formal at index INFO_TYPE in MT. */
|
||||
static inline struct ipcp_formal *
|
||||
static inline struct ipcp_lattice *
|
||||
ipcp_method_cval (struct cgraph_node *mt, int info_type)
|
||||
{
|
||||
return &(IPA_NODE_REF (mt)->ipcp_cval[info_type]);
|
||||
return &(IPA_NODE_REF (mt)->ipcp_lattices[info_type]);
|
||||
}
|
||||
|
||||
/* Given the jump function (TYPE, INFO_TYPE), compute a new value of CVAL.
|
||||
If TYPE is FORMAL_IPA_TYPE, the cval of the corresponding formal is
|
||||
drawn from MT. */
|
||||
static void
|
||||
ipcp_cval_compute (struct ipcp_formal *cval, struct cgraph_node *mt,
|
||||
enum jump_func_type type, union parameter_info *info_type)
|
||||
ipcp_cval_compute (struct ipcp_lattice *cval, struct cgraph_node *mt,
|
||||
enum jump_func_type type,
|
||||
union jump_func_value *info_type)
|
||||
{
|
||||
if (type == UNKNOWN_IPATYPE)
|
||||
ipcp_cval_set_cvalue_type (cval, BOTTOM);
|
||||
else if (type == CONST_IPATYPE)
|
||||
if (type == IPA_UNKNOWN)
|
||||
ipcp_cval_set_cvalue_type (cval, IPA_BOTTOM);
|
||||
else if (type == IPA_CONST)
|
||||
{
|
||||
ipcp_cval_set_cvalue_type (cval, CONST_VALUE);
|
||||
ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE);
|
||||
ipcp_cval_set_cvalue_type (cval, IPA_CONST_VALUE);
|
||||
ipcp_cval_set_cvalue (cval, info_type->constant, IPA_CONST_VALUE);
|
||||
}
|
||||
else if (type == CONST_IPATYPE_REF)
|
||||
else if (type == IPA_CONST_REF)
|
||||
{
|
||||
ipcp_cval_set_cvalue_type (cval, CONST_VALUE_REF);
|
||||
ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE_REF);
|
||||
ipcp_cval_set_cvalue_type (cval, IPA_CONST_VALUE_REF);
|
||||
ipcp_cval_set_cvalue (cval, info_type->constant, IPA_CONST_VALUE_REF);
|
||||
}
|
||||
else if (type == FORMAL_IPATYPE)
|
||||
else if (type == IPA_PASS_THROUGH)
|
||||
{
|
||||
enum cvalue_type type =
|
||||
enum ipa_lattice_type type =
|
||||
ipcp_cval_get_cvalue_type (ipcp_method_cval
|
||||
(mt, info_type->formal_id));
|
||||
ipcp_cval_set_cvalue_type (cval, type);
|
||||
@ -332,12 +333,12 @@ ipcp_cval_compute (struct ipcp_formal *cval, struct cgraph_node *mt,
|
||||
|
||||
/* True when CVAL1 and CVAL2 values are not the same. */
|
||||
static bool
|
||||
ipcp_cval_changed (struct ipcp_formal *cval1, struct ipcp_formal *cval2)
|
||||
ipcp_cval_changed (struct ipcp_lattice *cval1, struct ipcp_lattice *cval2)
|
||||
{
|
||||
if (ipcp_cval_get_cvalue_type (cval1) == ipcp_cval_get_cvalue_type (cval2))
|
||||
{
|
||||
if (ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE &&
|
||||
ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE_REF)
|
||||
if (ipcp_cval_get_cvalue_type (cval1) != IPA_CONST_VALUE
|
||||
&& ipcp_cval_get_cvalue_type (cval1) != IPA_CONST_VALUE_REF)
|
||||
return false;
|
||||
if (ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1),
|
||||
ipcp_cval_get_cvalue (cval2),
|
||||
@ -352,25 +353,33 @@ ipcp_cval_changed (struct ipcp_formal *cval1, struct ipcp_formal *cval2)
|
||||
static inline void
|
||||
ipcp_formal_create (struct cgraph_node *mt)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipcp_cval =
|
||||
XCNEWVEC (struct ipcp_formal, ipa_method_formal_count (mt));
|
||||
IPA_NODE_REF (mt)->ipcp_lattices =
|
||||
XCNEWVEC (struct ipcp_lattice, ipa_get_param_count (IPA_NODE_REF (mt)));
|
||||
}
|
||||
|
||||
/* Set cval structure of I-th formal of MT to CVAL. */
|
||||
static inline void
|
||||
ipcp_method_cval_set (struct cgraph_node *mt, int i, struct ipcp_formal *cval)
|
||||
ipcp_method_cval_set (struct cgraph_node *mt, int i, struct ipcp_lattice *cval)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval->cval_type;
|
||||
IPA_NODE_REF (mt)->ipcp_lattices[i].type = cval->type;
|
||||
ipcp_cval_set_cvalue (ipcp_method_cval (mt, i),
|
||||
ipcp_cval_get_cvalue (cval), cval->cval_type);
|
||||
ipcp_cval_get_cvalue (cval), cval->type);
|
||||
}
|
||||
|
||||
/* Set type of cval structure of formal I of MT to CVAL_TYPE1. */
|
||||
static inline void
|
||||
ipcp_method_cval_set_cvalue_type (struct cgraph_node *mt, int i,
|
||||
enum cvalue_type cval_type1)
|
||||
enum ipa_lattice_type type)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval_type1;
|
||||
IPA_NODE_REF (mt)->ipcp_lattices[i].type = type;
|
||||
}
|
||||
|
||||
/* Set type of cval structure of formal I of MT to CVAL_TYPE1. */
|
||||
static inline void
|
||||
ipcp_method_cval_set_lattice_type (struct cgraph_node *mt, int i,
|
||||
enum ipa_lattice_type type)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipcp_lattices[i].type = type;
|
||||
}
|
||||
|
||||
/* Print ipcp_cval data structures to F. */
|
||||
@ -385,22 +394,22 @@ ipcp_method_cval_print (FILE * f)
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
fprintf (f, "Printing cvals %s:\n", cgraph_node_name (node));
|
||||
count = ipa_method_formal_count (node);
|
||||
count = ipa_get_param_count (IPA_NODE_REF (node));
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i))
|
||||
== CONST_VALUE
|
||||
== IPA_CONST_VALUE
|
||||
|| ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) ==
|
||||
CONST_VALUE_REF)
|
||||
IPA_CONST_VALUE_REF)
|
||||
{
|
||||
fprintf (f, " param [%d]: ", i);
|
||||
fprintf (f, "type is CONST ");
|
||||
cvalue =
|
||||
ipcp_cval_get_cvalue (ipcp_method_cval (node, i))->value;
|
||||
ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
|
||||
print_generic_expr (f, cvalue, 0);
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
else if (ipcp_method_cval (node, i)->cval_type == TOP)
|
||||
else if (ipcp_method_cval (node, i)->type == IPA_TOP)
|
||||
fprintf (f, "param [%d]: type is TOP \n", i);
|
||||
else
|
||||
fprintf (f, "param [%d]: type is BOTTOM \n", i);
|
||||
@ -408,12 +417,12 @@ ipcp_method_cval_print (FILE * f)
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize ipcp_cval array of MT with TOP values.
|
||||
All cvals for a method's formal parameters are initialized to BOTTOM
|
||||
/* Initialize ipcp_cval array of MT with IPA_TOP values.
|
||||
All cvals for a method's formal parameters are initialized to IPA_BOTTOM
|
||||
The currently supported types are integer types, real types and
|
||||
Fortran constants (i.e. references to constants defined as
|
||||
const_decls). All other types are not analyzed and therefore are
|
||||
assigned with BOTTOM. */
|
||||
assigned with IPA_BOTTOM. */
|
||||
static void
|
||||
ipcp_method_cval_init (struct cgraph_node *mt)
|
||||
{
|
||||
@ -421,15 +430,15 @@ ipcp_method_cval_init (struct cgraph_node *mt)
|
||||
tree parm_tree;
|
||||
|
||||
ipcp_formal_create (mt);
|
||||
for (i = 0; i < ipa_method_formal_count (mt); i++)
|
||||
for (i = 0; i < ipa_get_param_count (IPA_NODE_REF (mt)) ; i++)
|
||||
{
|
||||
parm_tree = ipa_method_get_tree (mt, i);
|
||||
parm_tree = ipa_get_ith_param (IPA_NODE_REF (mt), i);
|
||||
if (INTEGRAL_TYPE_P (TREE_TYPE (parm_tree))
|
||||
|| SCALAR_FLOAT_TYPE_P (TREE_TYPE (parm_tree))
|
||||
|| POINTER_TYPE_P (TREE_TYPE (parm_tree)))
|
||||
ipcp_method_cval_set_cvalue_type (mt, i, TOP);
|
||||
ipcp_method_cval_set_cvalue_type (mt, i, IPA_TOP);
|
||||
else
|
||||
ipcp_method_cval_set_cvalue_type (mt, i, BOTTOM);
|
||||
ipcp_method_cval_set_cvalue_type (mt, i, IPA_BOTTOM);
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,13 +465,12 @@ constant_val_insert (tree parm1, tree val)
|
||||
/* build INTEGER_CST tree with type TREE_TYPE and
|
||||
value according to CVALUE. Return the tree. */
|
||||
static tree
|
||||
build_const_val (union parameter_info *cvalue, enum cvalue_type type,
|
||||
tree tree_type)
|
||||
build_const_val (tree cvalue, enum ipa_lattice_type type, tree tree_type)
|
||||
{
|
||||
tree const_val = NULL;
|
||||
|
||||
gcc_assert (ipcp_type_is_const (type));
|
||||
const_val = fold_convert (tree_type, cvalue->value);
|
||||
const_val = fold_convert (tree_type, cvalue);
|
||||
return const_val;
|
||||
}
|
||||
|
||||
@ -470,14 +478,14 @@ build_const_val (union parameter_info *cvalue, enum cvalue_type type,
|
||||
constant_val_insert(). */
|
||||
static void
|
||||
ipcp_propagate_const (struct cgraph_node *mt, int param,
|
||||
union parameter_info *cvalue, enum cvalue_type type)
|
||||
tree cvalue, enum ipa_lattice_type type)
|
||||
{
|
||||
tree const_val;
|
||||
tree parm_tree;
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "propagating const to %s\n", cgraph_node_name (mt));
|
||||
parm_tree = ipa_method_get_tree (mt, param);
|
||||
parm_tree = ipa_get_ith_param (IPA_NODE_REF (mt), param);
|
||||
const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree));
|
||||
constant_val_insert (parm_tree, const_val);
|
||||
}
|
||||
@ -514,10 +522,10 @@ ipcp_init_stage (void)
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
ipa_method_formal_compute_count (node);
|
||||
ipa_method_compute_tree_map (node);
|
||||
ipa_count_formal_params (node);
|
||||
ipa_create_param_decls_array (node);
|
||||
ipcp_method_cval_init (node);
|
||||
ipa_method_compute_modify (node);
|
||||
ipa_detect_param_modifications (node);
|
||||
ipcp_method_compute_scale (node);
|
||||
}
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
@ -525,23 +533,22 @@ ipcp_init_stage (void)
|
||||
/* building jump functions */
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
{
|
||||
ipa_callsite_compute_count (cs);
|
||||
if (ipa_callsite_param_count (cs)
|
||||
!= ipa_method_formal_count (cs->callee))
|
||||
ipa_count_arguments (cs);
|
||||
if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
|
||||
!= ipa_get_param_count (IPA_NODE_REF (cs->callee)))
|
||||
{
|
||||
/* Handle cases of functions with
|
||||
a variable number of parameters. */
|
||||
ipa_callsite_param_count_set (cs, 0);
|
||||
ipa_method_formal_count_set (cs->callee, 0);
|
||||
ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee));
|
||||
}
|
||||
else
|
||||
ipa_callsite_compute_param (cs);
|
||||
ipa_compute_jump_functions (cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if there are some formal parameters whose value is TOP.
|
||||
Change their values to BOTTOM, since they weren't determined. */
|
||||
/* Return true if there are some formal parameters whose value is IPA_TOP.
|
||||
Change their values to IPA_BOTTOM, since they weren't determined. */
|
||||
static bool
|
||||
ipcp_after_propagate (void)
|
||||
{
|
||||
@ -552,12 +559,12 @@ ipcp_after_propagate (void)
|
||||
prop_again = false;
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
count = ipa_method_formal_count (node);
|
||||
count = ipa_get_param_count (IPA_NODE_REF (node));
|
||||
for (i = 0; i < count; i++)
|
||||
if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) == TOP)
|
||||
if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) == IPA_TOP)
|
||||
{
|
||||
prop_again = true;
|
||||
ipcp_method_cval_set_cvalue_type (node, i, BOTTOM);
|
||||
ipcp_method_cval_set_cvalue_type (node, i, IPA_BOTTOM);
|
||||
}
|
||||
}
|
||||
return prop_again;
|
||||
@ -569,37 +576,39 @@ static void
|
||||
ipcp_propagate_stage (void)
|
||||
{
|
||||
int i;
|
||||
struct ipcp_formal cval1 = { BOTTOM, {0} }, cval = { BOTTOM, {0} };
|
||||
struct ipcp_formal *cval2;
|
||||
struct ipcp_lattice cval1 = { IPA_BOTTOM, NULL }, cval = { IPA_BOTTOM, NULL };
|
||||
struct ipcp_lattice *cval2;
|
||||
struct cgraph_node *mt, *callee;
|
||||
struct cgraph_edge *cs;
|
||||
struct ipa_jump_func *jump_func;
|
||||
enum jump_func_type type;
|
||||
union parameter_info *info_type;
|
||||
ipa_methodlist_p wl;
|
||||
union jump_func_value *jf_value;
|
||||
struct ipa_func_list *wl;
|
||||
int count;
|
||||
|
||||
/* Initialize worklist to contain all methods. */
|
||||
wl = ipa_methodlist_init ();
|
||||
while (ipa_methodlist_not_empty (wl))
|
||||
/* Initialize worklist to contain all functions. */
|
||||
wl = ipa_init_func_list ();
|
||||
while (wl)
|
||||
{
|
||||
mt = ipa_remove_method (&wl);
|
||||
mt = ipa_pop_func_from_list (&wl);
|
||||
for (cs = mt->callees; cs; cs = cs->next_callee)
|
||||
{
|
||||
callee = ipa_callsite_callee (cs);
|
||||
count = ipa_callsite_param_count (cs);
|
||||
callee = cs->callee;
|
||||
if (ipa_is_called_with_var_arguments (IPA_NODE_REF (callee)))
|
||||
continue;
|
||||
count = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
jump_func = ipa_callsite_param (cs, i);
|
||||
type = get_type (jump_func);
|
||||
info_type = ipa_jf_get_info_type (jump_func);
|
||||
ipcp_cval_compute (&cval1, mt, type, info_type);
|
||||
jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
|
||||
type = jump_func->type;
|
||||
jf_value = &jump_func->value;
|
||||
ipcp_cval_compute (&cval1, mt, type, jf_value);
|
||||
cval2 = ipcp_method_cval (callee, i);
|
||||
ipcp_cval_meet (&cval, &cval1, cval2);
|
||||
if (ipcp_cval_changed (&cval, cval2))
|
||||
{
|
||||
ipcp_method_cval_set (callee, i, &cval);
|
||||
ipa_add_method (&wl, callee);
|
||||
ipa_push_func_to_list (&wl, callee);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -613,7 +622,7 @@ ipcp_iterate_stage (void)
|
||||
{
|
||||
ipcp_propagate_stage ();
|
||||
if (ipcp_after_propagate ())
|
||||
/* Some cvals have changed from TOP to BOTTOM.
|
||||
/* Some cvals have changed from IPA_TOP to IPA_BOTTOM.
|
||||
This change should be propagated. */
|
||||
ipcp_propagate_stage ();
|
||||
}
|
||||
@ -646,27 +655,30 @@ ipcp_callsite_param_print (FILE * f)
|
||||
{
|
||||
fprintf (f, "callsite %s ", cgraph_node_name (node));
|
||||
fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee));
|
||||
count = ipa_callsite_param_count (cs);
|
||||
|
||||
if (ipa_is_called_with_var_arguments (IPA_NODE_REF (cs->callee)))
|
||||
continue;
|
||||
|
||||
count = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
jump_func = ipa_callsite_param (cs, i);
|
||||
type = get_type (jump_func);
|
||||
jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
|
||||
type = jump_func->type;
|
||||
|
||||
fprintf (f, " param %d: ", i);
|
||||
if (type == UNKNOWN_IPATYPE)
|
||||
if (type == IPA_UNKNOWN)
|
||||
fprintf (f, "UNKNOWN\n");
|
||||
else if (type == CONST_IPATYPE || type == CONST_IPATYPE_REF)
|
||||
else if (type == IPA_CONST || type == IPA_CONST_REF)
|
||||
{
|
||||
info_type = ipa_jf_get_info_type (jump_func)->value;
|
||||
info_type = jump_func->value.constant;
|
||||
fprintf (f, "CONST : ");
|
||||
print_generic_expr (f, info_type, 0);
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
else if (type == FORMAL_IPATYPE)
|
||||
else if (type == IPA_PASS_THROUGH)
|
||||
{
|
||||
fprintf (f, "FORMAL : ");
|
||||
fprintf (f, "%d\n",
|
||||
ipa_jf_get_info_type (jump_func)->formal_id);
|
||||
fprintf (f, "PASS THROUGH : ");
|
||||
fprintf (f, "%d\n", jump_func->value.formal_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -818,8 +830,8 @@ ipcp_structures_print (FILE * f)
|
||||
{
|
||||
ipcp_method_cval_print (f);
|
||||
ipcp_method_scale_print (f);
|
||||
ipa_method_tree_print (f);
|
||||
ipa_method_modify_print (f);
|
||||
ipa_print_all_tree_maps (f);
|
||||
ipa_print_all_params_modified (f);
|
||||
ipcp_callsite_param_print (f);
|
||||
}
|
||||
|
||||
@ -842,15 +854,15 @@ ipcp_profile_print (FILE * f)
|
||||
operates according to the flags sent. PARM_TREE is the
|
||||
formal's tree found to be constant. CVALUE represents the constant. */
|
||||
static struct ipa_replace_map *
|
||||
ipcp_replace_map_create (struct function *func, enum cvalue_type type,
|
||||
tree parm_tree, union parameter_info *cvalue)
|
||||
ipcp_replace_map_create (struct function *func, enum ipa_lattice_type type,
|
||||
tree parm_tree, tree cvalue)
|
||||
{
|
||||
struct ipa_replace_map *replace_map;
|
||||
tree const_val;
|
||||
|
||||
replace_map = XCNEW (struct ipa_replace_map);
|
||||
gcc_assert (ipcp_type_is_const (type));
|
||||
if (type != CONST_VALUE_REF
|
||||
if (type != IPA_CONST_VALUE_REF
|
||||
&& is_gimple_reg (parm_tree) && gimple_default_def (func, parm_tree)
|
||||
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_default_def (func, parm_tree)))
|
||||
{
|
||||
@ -882,21 +894,21 @@ ipcp_redirect (struct cgraph_edge *cs)
|
||||
int i, count;
|
||||
struct ipa_jump_func *jump_func;
|
||||
enum jump_func_type type;
|
||||
enum cvalue_type cval_type;
|
||||
enum ipa_lattice_type lattice_type;
|
||||
|
||||
caller = cs->caller;
|
||||
callee = cs->callee;
|
||||
orig_callee = ipcp_method_orig_node (callee);
|
||||
count = ipa_method_formal_count (orig_callee);
|
||||
count = ipa_get_param_count (IPA_NODE_REF (orig_callee));
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
cval_type =
|
||||
lattice_type =
|
||||
ipcp_cval_get_cvalue_type (ipcp_method_cval (orig_callee, i));
|
||||
if (ipcp_type_is_const (cval_type))
|
||||
if (ipcp_type_is_const (lattice_type))
|
||||
{
|
||||
jump_func = ipa_callsite_param (cs, i);
|
||||
type = get_type (jump_func);
|
||||
if (type != CONST_IPATYPE && type != CONST_IPATYPE_REF)
|
||||
jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
|
||||
type = jump_func->type;
|
||||
if (type != IPA_CONST && type != IPA_CONST_REF)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -993,23 +1005,24 @@ ipcp_insert_stage (void)
|
||||
{
|
||||
struct cgraph_node *node, *node1 = NULL;
|
||||
int i, const_param;
|
||||
union parameter_info *cvalue;
|
||||
tree cvalue;
|
||||
VEC (cgraph_edge_p, heap) * redirect_callers;
|
||||
varray_type replace_trees;
|
||||
struct cgraph_edge *cs;
|
||||
int node_callers, count;
|
||||
tree parm_tree;
|
||||
enum cvalue_type type;
|
||||
enum ipa_lattice_type type;
|
||||
struct ipa_replace_map *replace_param;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
/* Propagation of the constant is forbidden in
|
||||
certain conditions. */
|
||||
if (!node->analyzed || ipcp_method_dont_insert_const (node))
|
||||
if (!node->analyzed || ipcp_method_dont_insert_const (node)
|
||||
|| ipa_is_called_with_var_arguments (IPA_NODE_REF (node)))
|
||||
continue;
|
||||
const_param = 0;
|
||||
count = ipa_method_formal_count (node);
|
||||
count = ipa_get_param_count (IPA_NODE_REF (node));
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
|
||||
@ -1025,7 +1038,7 @@ ipcp_insert_stage (void)
|
||||
if (ipcp_type_is_const (type))
|
||||
{
|
||||
cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
|
||||
parm_tree = ipa_method_get_tree (node, i);
|
||||
parm_tree = ipa_get_ith_param (IPA_NODE_REF (node), i);
|
||||
replace_param =
|
||||
ipcp_replace_map_create (DECL_STRUCT_FUNCTION (node->decl),
|
||||
type, parm_tree, cvalue);
|
||||
@ -1063,8 +1076,8 @@ ipcp_insert_stage (void)
|
||||
if (ipcp_type_is_const (type))
|
||||
{
|
||||
cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i));
|
||||
parm_tree = ipa_method_get_tree (node, i);
|
||||
if (type != CONST_VALUE_REF && !is_gimple_reg (parm_tree))
|
||||
parm_tree = ipa_get_ith_param (IPA_NODE_REF (node), i);
|
||||
if (type != IPA_CONST_VALUE_REF && !is_gimple_reg (parm_tree))
|
||||
ipcp_propagate_const (node1, i, cvalue, type);
|
||||
}
|
||||
}
|
||||
@ -1093,10 +1106,10 @@ ipcp_driver (void)
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "\nIPA constant propagation start:\n");
|
||||
ipa_nodes_create ();
|
||||
ipa_edges_create ();
|
||||
ipa_create_all_node_params ();
|
||||
ipa_create_all_edge_args ();
|
||||
/* 1. Call the init stage to initialize
|
||||
the ipa_node and ipa_edge structures. */
|
||||
the ipa_node_params and ipa_edge_args structures. */
|
||||
ipcp_init_stage ();
|
||||
if (dump_file)
|
||||
{
|
||||
@ -1120,9 +1133,8 @@ ipcp_driver (void)
|
||||
ipcp_profile_print (dump_file);
|
||||
}
|
||||
/* Free all IPCP structures. */
|
||||
ipa_free ();
|
||||
ipa_nodes_free ();
|
||||
ipa_edges_free ();
|
||||
ipa_free_all_node_params ();
|
||||
ipa_free_all_edge_args ();
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "\nIPA constant propagation end\n");
|
||||
cgraph_remove_unreachable_nodes (true, NULL);
|
||||
|
479
gcc/ipa-prop.c
479
gcc/ipa-prop.c
@ -31,197 +31,88 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "flags.h"
|
||||
#include "timevar.h"
|
||||
|
||||
/* This file contains interfaces that can be used for various IPA
|
||||
optimizations:
|
||||
|
||||
- ipa_methodlist interface - It is used to create and handle a temporary
|
||||
worklist used in the propagation stage of IPCP. (can be used for more
|
||||
IPA optimizations).
|
||||
|
||||
- ipa_callsite interface - for each callsite this interface creates and
|
||||
handles ipa_edge structure associated with it.
|
||||
|
||||
- ipa_method interface - for each method this interface creates and
|
||||
handles ipa_node structure associated with it. */
|
||||
|
||||
/* ipa_methodlist interface. */
|
||||
|
||||
/* Create a new worklist node. */
|
||||
static inline ipa_methodlist_p
|
||||
ipa_create_methodlist_node (void)
|
||||
{
|
||||
return (ipa_methodlist_p) xcalloc (1, sizeof (struct ipa_methodlist));
|
||||
}
|
||||
|
||||
/* Return true if worklist WL is empty. */
|
||||
bool
|
||||
ipa_methodlist_not_empty (ipa_methodlist_p wl)
|
||||
{
|
||||
return (wl != NULL);
|
||||
}
|
||||
|
||||
/* Return the method in worklist element WL. */
|
||||
static inline struct cgraph_node *
|
||||
ipa_methodlist_method (ipa_methodlist_p wl)
|
||||
{
|
||||
return wl->method_p;
|
||||
}
|
||||
|
||||
/* Make worklist element WL point to method MT in the callgraph. */
|
||||
static inline void
|
||||
ipa_methodlist_method_set (ipa_methodlist_p wl, struct cgraph_node *mt)
|
||||
{
|
||||
wl->method_p = mt;
|
||||
}
|
||||
|
||||
/* Return the next element in the worklist following worklist
|
||||
element WL. */
|
||||
static inline ipa_methodlist_p
|
||||
ipa_methodlist_next_method (ipa_methodlist_p wl)
|
||||
{
|
||||
return wl->next_method;
|
||||
}
|
||||
|
||||
/* Set worklist element WL1 to point to worklist element WL2. */
|
||||
static inline void
|
||||
ipa_methodlist_next_method_set (ipa_methodlist_p wl1, ipa_methodlist_p wl2)
|
||||
{
|
||||
wl1->next_method = wl2;
|
||||
}
|
||||
|
||||
/* Initialize worklist to contain all methods. */
|
||||
ipa_methodlist_p
|
||||
ipa_methodlist_init (void)
|
||||
/* Initialize worklist to contain all functions. */
|
||||
struct ipa_func_list *
|
||||
ipa_init_func_list (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
ipa_methodlist_p wl;
|
||||
struct ipa_func_list * wl;
|
||||
|
||||
wl = NULL;
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
ipa_add_method (&wl, node);
|
||||
ipa_push_func_to_list (&wl, node);
|
||||
|
||||
return wl;
|
||||
}
|
||||
|
||||
/* Add method MT to the worklist. Set worklist element WL
|
||||
/* Add cgraph node MT to the worklist. Set worklist element WL
|
||||
to point to MT. */
|
||||
void
|
||||
ipa_add_method (ipa_methodlist_p * wl, struct cgraph_node *mt)
|
||||
ipa_push_func_to_list (struct ipa_func_list **wl, struct cgraph_node *mt)
|
||||
{
|
||||
ipa_methodlist_p temp;
|
||||
struct ipa_func_list *temp;
|
||||
|
||||
temp = ipa_create_methodlist_node ();
|
||||
ipa_methodlist_method_set (temp, mt);
|
||||
ipa_methodlist_next_method_set (temp, *wl);
|
||||
temp = xcalloc (1, sizeof (struct ipa_func_list));
|
||||
temp->node = mt;
|
||||
temp->next = *wl;
|
||||
*wl = temp;
|
||||
}
|
||||
|
||||
/* Remove a method from the worklist. WL points to the first
|
||||
/* Remove a function from the worklist. WL points to the first
|
||||
element in the list, which is removed. */
|
||||
struct cgraph_node *
|
||||
ipa_remove_method (ipa_methodlist_p * wl)
|
||||
ipa_pop_func_from_list (struct ipa_func_list ** wl)
|
||||
{
|
||||
ipa_methodlist_p first;
|
||||
struct cgraph_node *return_method;
|
||||
struct ipa_func_list *first;
|
||||
struct cgraph_node *return_func;
|
||||
|
||||
first = *wl;
|
||||
*wl = ipa_methodlist_next_method (*wl);
|
||||
return_method = ipa_methodlist_method (first);
|
||||
*wl = (*wl)->next;
|
||||
return_func = first->node;
|
||||
free (first);
|
||||
return return_method;
|
||||
return return_func;
|
||||
}
|
||||
|
||||
/* ipa_method interface. */
|
||||
|
||||
/* Return number of formals of method MT. */
|
||||
int
|
||||
ipa_method_formal_count (struct cgraph_node *mt)
|
||||
{
|
||||
return IPA_NODE_REF (mt)->ipa_arg_num;
|
||||
}
|
||||
|
||||
/* Set number of formals of method MT to I. */
|
||||
void
|
||||
ipa_method_formal_count_set (struct cgraph_node *mt, int i)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipa_arg_num = i;
|
||||
}
|
||||
|
||||
/* Return whether I-th formal of MT is modified in MT. */
|
||||
static inline bool
|
||||
ipa_method_is_modified (struct cgraph_node *mt, int i)
|
||||
{
|
||||
return IPA_NODE_REF (mt)->ipa_mod[i];
|
||||
}
|
||||
|
||||
/* Return the tree of I-th formal of MT. */
|
||||
tree
|
||||
ipa_method_get_tree (struct cgraph_node *mt, int i)
|
||||
{
|
||||
return IPA_NODE_REF (mt)->ipa_param_tree[i];
|
||||
}
|
||||
|
||||
/* Create tree map structure for MT. */
|
||||
static inline void
|
||||
ipa_method_tree_map_create (struct cgraph_node *mt)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipa_param_tree =
|
||||
XCNEWVEC (tree, ipa_method_formal_count (mt));
|
||||
}
|
||||
|
||||
/* Create modify structure for MT. */
|
||||
static inline void
|
||||
ipa_method_modify_create (struct cgraph_node *mt)
|
||||
{
|
||||
((struct ipa_node *) mt->aux)->ipa_mod =
|
||||
XCNEWVEC (bool, ipa_method_formal_count (mt));
|
||||
}
|
||||
|
||||
/* Set modify of I-th formal of MT to VAL. */
|
||||
static inline void
|
||||
ipa_method_modify_set (struct cgraph_node *mt, int i, bool val)
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipa_mod[i] = val;
|
||||
}
|
||||
|
||||
/* Return index of the formal whose tree is PTREE in method MT. */
|
||||
/* Return index of the formal whose tree is ptree in function which corresponds
|
||||
to info. */
|
||||
static int
|
||||
ipa_method_tree_map (struct cgraph_node *mt, tree ptree)
|
||||
ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
count = ipa_method_formal_count (mt);
|
||||
count = ipa_get_param_count (info);
|
||||
for (i = 0; i < count; i++)
|
||||
if (IPA_NODE_REF (mt)->ipa_param_tree[i] == ptree)
|
||||
if (ipa_get_ith_param(info, i) == ptree)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Insert the formal trees to the ipa_param_tree array in method MT. */
|
||||
/* Insert the formal trees to the param_decls array in function MT. */
|
||||
void
|
||||
ipa_method_compute_tree_map (struct cgraph_node *mt)
|
||||
ipa_create_param_decls_array (struct cgraph_node *mt)
|
||||
{
|
||||
tree fndecl;
|
||||
tree fnargs;
|
||||
tree parm;
|
||||
int param_num;
|
||||
struct ipa_node_params *info = IPA_NODE_REF (mt);
|
||||
|
||||
ipa_method_tree_map_create (mt);
|
||||
info->param_decls = XCNEWVEC (tree, ipa_get_param_count (info));
|
||||
fndecl = mt->decl;
|
||||
fnargs = DECL_ARGUMENTS (fndecl);
|
||||
param_num = 0;
|
||||
for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
|
||||
{
|
||||
IPA_NODE_REF (mt)->ipa_param_tree[param_num] = parm;
|
||||
info->param_decls[param_num] = parm;
|
||||
param_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Count number of formals in MT. Insert the result to the
|
||||
ipa_node. */
|
||||
ipa_node_params. */
|
||||
void
|
||||
ipa_method_formal_compute_count (struct cgraph_node *mt)
|
||||
ipa_count_formal_params (struct cgraph_node *mt)
|
||||
{
|
||||
tree fndecl;
|
||||
tree fnargs;
|
||||
@ -233,57 +124,48 @@ ipa_method_formal_compute_count (struct cgraph_node *mt)
|
||||
param_num = 0;
|
||||
for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
|
||||
param_num++;
|
||||
ipa_method_formal_count_set (mt, param_num);
|
||||
ipa_set_param_count (IPA_NODE_REF (mt), param_num);
|
||||
}
|
||||
|
||||
/* Check STMT to detect whether a formal is modified within MT,
|
||||
the appropriate entry is updated in the ipa_mod array of ipa_node
|
||||
(associated with MT). */
|
||||
/* Check STMT to detect whether a formal is modified within MT, the appropriate
|
||||
entry is updated in the modified_flags array of ipa_node_params (associated
|
||||
with MT). */
|
||||
static void
|
||||
ipa_method_modify_stmt (struct cgraph_node *mt, tree stmt)
|
||||
ipa_check_stmt_modifications (struct cgraph_node *mt, tree stmt)
|
||||
{
|
||||
int i, j;
|
||||
int index, j;
|
||||
tree parm_decl;
|
||||
struct ipa_node_params *info;
|
||||
|
||||
switch (TREE_CODE (stmt))
|
||||
{
|
||||
case GIMPLE_MODIFY_STMT:
|
||||
if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == PARM_DECL)
|
||||
{
|
||||
info = IPA_NODE_REF (mt);
|
||||
parm_decl = GIMPLE_STMT_OPERAND (stmt, 0);
|
||||
i = ipa_method_tree_map (mt, parm_decl);
|
||||
if (i >= 0)
|
||||
ipa_method_modify_set (mt, i, true);
|
||||
index = ipa_get_param_decl_index (info, parm_decl);
|
||||
if (index >= 0)
|
||||
info->modified_flags[index] = true;
|
||||
}
|
||||
break;
|
||||
case ASM_EXPR:
|
||||
/* Asm code could modify any of the parameters. */
|
||||
for (j = 0; j < ipa_method_formal_count (mt); j++)
|
||||
ipa_method_modify_set (mt, j, true);
|
||||
info = IPA_NODE_REF (mt);
|
||||
for (j = 0; j < ipa_get_param_count (IPA_NODE_REF (mt)); j++)
|
||||
info->modified_flags[j] = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize ipa_mod array of MT. */
|
||||
static void
|
||||
ipa_method_modify_init (struct cgraph_node *mt)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
ipa_method_modify_create (mt);
|
||||
count = ipa_method_formal_count (mt);
|
||||
for (i = 0; i < count; i++)
|
||||
ipa_method_modify_set (mt, i, false);
|
||||
}
|
||||
|
||||
/* The modify computation driver for MT. Compute which formal arguments
|
||||
of method MT are locally modified. Formals may be modified in MT
|
||||
of function MT are locally modified. Formals may be modified in MT
|
||||
if their address is taken, or if
|
||||
they appear on the left hand side of an assignment. */
|
||||
void
|
||||
ipa_method_compute_modify (struct cgraph_node *mt)
|
||||
ipa_detect_param_modifications (struct cgraph_node *mt)
|
||||
{
|
||||
tree decl;
|
||||
tree body;
|
||||
@ -292,29 +174,31 @@ ipa_method_compute_modify (struct cgraph_node *mt)
|
||||
struct function *func;
|
||||
block_stmt_iterator bsi;
|
||||
tree stmt, parm_tree;
|
||||
struct ipa_node_params *info = IPA_NODE_REF (mt);
|
||||
|
||||
if (ipa_method_formal_count (mt) == 0)
|
||||
if (ipa_get_param_count (info) == 0)
|
||||
return;
|
||||
|
||||
ipa_method_modify_init (mt);
|
||||
count = ipa_get_param_count (info);
|
||||
info->modified_flags = XCNEWVEC (bool, count);
|
||||
decl = mt->decl;
|
||||
count = ipa_method_formal_count (mt);
|
||||
/* ??? Handle pending sizes case. Set all parameters
|
||||
of the method to be modified. */
|
||||
of the function to be modified. */
|
||||
|
||||
if (DECL_UNINLINABLE (decl))
|
||||
{
|
||||
for (j = 0; j < count; j++)
|
||||
ipa_method_modify_set (mt, j, true);
|
||||
info->modified_flags[j] = true;
|
||||
|
||||
return;
|
||||
}
|
||||
/* Formals whose address is taken are considered modified. */
|
||||
for (j = 0; j < count; j++)
|
||||
{
|
||||
parm_tree = ipa_method_get_tree (mt, j);
|
||||
parm_tree = ipa_get_ith_param (info, j);
|
||||
if (!is_gimple_reg (parm_tree)
|
||||
&& TREE_ADDRESSABLE (parm_tree))
|
||||
ipa_method_modify_set (mt, j, true);
|
||||
info->modified_flags[j] = true;
|
||||
}
|
||||
body = DECL_SAVED_TREE (decl);
|
||||
if (body != NULL)
|
||||
@ -325,171 +209,94 @@ ipa_method_compute_modify (struct cgraph_node *mt)
|
||||
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
|
||||
{
|
||||
stmt = bsi_stmt (bsi);
|
||||
ipa_method_modify_stmt (mt, stmt);
|
||||
ipa_check_stmt_modifications (mt, stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ipa_callsite interface. */
|
||||
|
||||
/* Return number of arguments in callsite CS. */
|
||||
int
|
||||
ipa_callsite_param_count (struct cgraph_edge *cs)
|
||||
{
|
||||
return IPA_EDGE_REF (cs)->ipa_param_num;
|
||||
}
|
||||
|
||||
/* Set number of arguments in callsite CS to I. */
|
||||
void
|
||||
ipa_callsite_param_count_set (struct cgraph_edge *cs, int i)
|
||||
{
|
||||
IPA_EDGE_REF (cs)->ipa_param_num = i;
|
||||
}
|
||||
|
||||
/* Return the jump function (ipa_jump_func struct) for argument I of
|
||||
callsite CS. */
|
||||
struct ipa_jump_func *
|
||||
ipa_callsite_param (struct cgraph_edge *cs, int i)
|
||||
{
|
||||
return &(IPA_EDGE_REF (cs)->ipa_param_map[i]);
|
||||
}
|
||||
|
||||
/* return the callee (cgraph_node) of callsite CS. */
|
||||
struct cgraph_node *
|
||||
ipa_callsite_callee (struct cgraph_edge *cs)
|
||||
{
|
||||
return cs->callee;
|
||||
}
|
||||
|
||||
/* Set field 'type' of jump function (ipa_jump_func struct) of argument I
|
||||
in callsite CS. */
|
||||
static inline void
|
||||
ipa_callsite_param_set_type (struct cgraph_edge *cs, int i,
|
||||
enum jump_func_type type1)
|
||||
{
|
||||
IPA_EDGE_REF (cs)->ipa_param_map[i].type = type1;
|
||||
}
|
||||
|
||||
/* Set FORMAL as 'info_type' field of jump function (ipa_jump_func struct)
|
||||
of argument I of callsite CS. */
|
||||
static inline void
|
||||
ipa_callsite_param_set_info_type_formal (struct cgraph_edge *cs, int i,
|
||||
unsigned int formal)
|
||||
{
|
||||
ipa_callsite_param (cs, i)->info_type.formal_id = formal;
|
||||
}
|
||||
|
||||
/* Set int-valued INFO_TYPE1 as 'info_type' field of
|
||||
jump function (ipa_jump_func struct) of argument I of callsite CS. */
|
||||
static inline void
|
||||
ipa_callsite_param_set_info_type (struct cgraph_edge *cs, int i,
|
||||
tree info_type1)
|
||||
{
|
||||
ipa_callsite_param (cs, i)->info_type.value = info_type1;
|
||||
}
|
||||
|
||||
/* Allocate space for callsite CS. */
|
||||
static inline void
|
||||
ipa_callsite_param_map_create (struct cgraph_edge *cs)
|
||||
{
|
||||
IPA_EDGE_REF (cs)->ipa_param_map =
|
||||
XCNEWVEC (struct ipa_jump_func, ipa_callsite_param_count (cs));
|
||||
}
|
||||
|
||||
/* Return the call expr tree related to callsite CS. */
|
||||
static inline tree
|
||||
ipa_callsite_tree (struct cgraph_edge *cs)
|
||||
{
|
||||
return cs->call_stmt;
|
||||
}
|
||||
|
||||
/* Return the caller (cgraph_node) of CS. */
|
||||
static inline struct cgraph_node *
|
||||
ipa_callsite_caller (struct cgraph_edge *cs)
|
||||
{
|
||||
return cs->caller;
|
||||
}
|
||||
|
||||
/* Count number of arguments callsite CS has and store it in
|
||||
ipa_edge structure corresponding to this callsite. */
|
||||
ipa_edge_args structure corresponding to this callsite. */
|
||||
void
|
||||
ipa_callsite_compute_count (struct cgraph_edge *cs)
|
||||
ipa_count_arguments (struct cgraph_edge *cs)
|
||||
{
|
||||
tree call_tree;
|
||||
int arg_num;
|
||||
|
||||
call_tree = get_call_expr_in (ipa_callsite_tree (cs));
|
||||
call_tree = get_call_expr_in (cs->call_stmt);
|
||||
gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
|
||||
arg_num = call_expr_nargs (call_tree);
|
||||
ipa_callsite_param_count_set (cs, arg_num);
|
||||
ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num);
|
||||
}
|
||||
|
||||
/* Compute jump function for all arguments of callsite CS
|
||||
and insert the information in the ipa_param_map array
|
||||
in the ipa_edge corresponding to this callsite. (Explanation
|
||||
on jump functions is in ipa-prop.h). */
|
||||
and insert the information in the jump_functions array
|
||||
in the ipa_edge_args corresponding to this callsite. */
|
||||
void
|
||||
ipa_callsite_compute_param (struct cgraph_edge *cs)
|
||||
ipa_compute_jump_functions (struct cgraph_edge *cs)
|
||||
{
|
||||
tree call_tree;
|
||||
tree arg, cst_decl;
|
||||
int arg_num;
|
||||
int i;
|
||||
struct cgraph_node *mt;
|
||||
tree parm_decl;
|
||||
struct function *curr_cfun;
|
||||
call_expr_arg_iterator iter;
|
||||
struct ipa_edge_args *args = IPA_EDGE_REF (cs);
|
||||
|
||||
if (ipa_callsite_param_count (cs) == 0)
|
||||
if (ipa_get_cs_argument_count (args) == 0)
|
||||
return;
|
||||
ipa_callsite_param_map_create (cs);
|
||||
call_tree = get_call_expr_in (ipa_callsite_tree (cs));
|
||||
args->jump_functions = XCNEWVEC (struct ipa_jump_func,
|
||||
ipa_get_cs_argument_count (args));
|
||||
call_tree = get_call_expr_in (cs->call_stmt);
|
||||
gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
|
||||
arg_num = 0;
|
||||
|
||||
FOR_EACH_CALL_EXPR_ARG (arg, iter, call_tree)
|
||||
{
|
||||
/* If the formal parameter was passed as argument, we store
|
||||
FORMAL_IPATYPE and its index in the caller as the jump function
|
||||
IPA_PASS_THROUGH and its index in the caller as the jump function
|
||||
of this argument. */
|
||||
if ((TREE_CODE (arg) == SSA_NAME
|
||||
&& TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL)
|
||||
|| TREE_CODE (arg) == PARM_DECL)
|
||||
{
|
||||
mt = ipa_callsite_caller (cs);
|
||||
struct ipa_node_params *info;
|
||||
int index;
|
||||
|
||||
mt = cs->caller;
|
||||
info = IPA_NODE_REF (mt);
|
||||
parm_decl = TREE_CODE (arg) == PARM_DECL ? arg : SSA_NAME_VAR (arg);
|
||||
|
||||
i = ipa_method_tree_map (mt, parm_decl);
|
||||
if (TREE_CODE (arg) == SSA_NAME && IS_VALID_TREE_MAP_INDEX (i))
|
||||
index = ipa_get_param_decl_index (info, parm_decl);
|
||||
if (TREE_CODE (arg) == SSA_NAME && IS_VALID_JUMP_FUNC_INDEX (index))
|
||||
{
|
||||
curr_cfun = DECL_STRUCT_FUNCTION (mt->decl);
|
||||
if (!gimple_default_def (curr_cfun, parm_decl)
|
||||
|| gimple_default_def (curr_cfun, parm_decl) != arg)
|
||||
ipa_method_modify_set (mt, i, true);
|
||||
info->modified_flags[index] = true;
|
||||
}
|
||||
if (!IS_VALID_TREE_MAP_INDEX (i) || ipa_method_is_modified (mt, i))
|
||||
ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE);
|
||||
if (!IS_VALID_JUMP_FUNC_INDEX (index) || info->modified_flags[index])
|
||||
args->jump_functions[arg_num].type = IPA_UNKNOWN;
|
||||
else
|
||||
{
|
||||
ipa_callsite_param_set_type (cs, arg_num, FORMAL_IPATYPE);
|
||||
ipa_callsite_param_set_info_type_formal (cs, arg_num, i);
|
||||
args->jump_functions[arg_num].type = IPA_PASS_THROUGH;
|
||||
args->jump_functions[arg_num].value.formal_id = index;
|
||||
}
|
||||
}
|
||||
/* If a constant value was passed as argument,
|
||||
we store CONST_IPATYPE and its value as the jump function
|
||||
we store IPA_CONST and its value as the jump function
|
||||
of this argument. */
|
||||
else if (TREE_CODE (arg) == INTEGER_CST
|
||||
|| TREE_CODE (arg) == REAL_CST
|
||||
|| TREE_CODE (arg) == FIXED_CST)
|
||||
{
|
||||
ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE);
|
||||
ipa_callsite_param_set_info_type (cs, arg_num, arg);
|
||||
args->jump_functions[arg_num].type = IPA_CONST;
|
||||
args->jump_functions[arg_num].value.constant = arg;
|
||||
}
|
||||
/* This is for the case of Fortran. If the address of a const_decl
|
||||
was passed as argument then we store
|
||||
CONST_IPATYPE_REF/CONST_IPATYPE_REF and the constant
|
||||
was passed as argument then we store
|
||||
IPA_CONST_REF/IPA_CONST_REF and the constant
|
||||
value as the jump function corresponding to this argument. */
|
||||
else if (TREE_CODE (arg) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (arg, 0)) == CONST_DECL)
|
||||
@ -499,121 +306,90 @@ ipa_callsite_compute_param (struct cgraph_edge *cs)
|
||||
|| TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST
|
||||
|| TREE_CODE (DECL_INITIAL (cst_decl)) == FIXED_CST)
|
||||
{
|
||||
ipa_callsite_param_set_type (cs, arg_num,
|
||||
CONST_IPATYPE_REF);
|
||||
ipa_callsite_param_set_info_type (cs, arg_num,
|
||||
DECL_INITIAL (cst_decl));
|
||||
args->jump_functions[arg_num].type = IPA_CONST_REF;
|
||||
args->jump_functions[arg_num].value.constant = cst_decl;
|
||||
}
|
||||
}
|
||||
else
|
||||
ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE);
|
||||
args->jump_functions[arg_num].type = IPA_UNKNOWN;
|
||||
arg_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return type of jump function JF. */
|
||||
enum jump_func_type
|
||||
get_type (struct ipa_jump_func *jf)
|
||||
{
|
||||
return jf->type;
|
||||
}
|
||||
|
||||
/* Return info type of jump function JF. */
|
||||
union parameter_info *
|
||||
ipa_jf_get_info_type (struct ipa_jump_func *jf)
|
||||
{
|
||||
return &(jf->info_type);
|
||||
}
|
||||
|
||||
/* Allocate and initialize ipa_node structure.
|
||||
cgraph_node NODE points to the new allocated ipa_node. */
|
||||
/* Allocate and initialize ipa_node_params structure for the given cgraph
|
||||
node. */
|
||||
void
|
||||
ipa_node_create (struct cgraph_node *node)
|
||||
ipa_create_node_params (struct cgraph_node *node)
|
||||
{
|
||||
node->aux = xcalloc (1, sizeof (struct ipa_node));
|
||||
node->aux = xcalloc (1, sizeof (struct ipa_node_params));
|
||||
}
|
||||
|
||||
/* Allocate and initialize ipa_node structure for all
|
||||
/* Allocate and initialize ipa_node_params structure for all
|
||||
nodes in callgraph. */
|
||||
void
|
||||
ipa_nodes_create (void)
|
||||
ipa_create_all_node_params (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
ipa_node_create (node);
|
||||
ipa_create_node_params (node);
|
||||
}
|
||||
|
||||
/* Allocate and initialize ipa_edge structure. */
|
||||
void
|
||||
ipa_edges_create (void)
|
||||
ipa_create_all_edge_args (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *cs;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
cs->aux = xcalloc (1, sizeof (struct ipa_edge));
|
||||
}
|
||||
|
||||
/* Free ipa_node structure. */
|
||||
void
|
||||
ipa_nodes_free (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
free (node->aux);
|
||||
node->aux = NULL;
|
||||
}
|
||||
cs->aux = xcalloc (1, sizeof (struct ipa_edge_args));
|
||||
}
|
||||
|
||||
/* Free ipa_edge structure. */
|
||||
void
|
||||
ipa_edges_free (void)
|
||||
ipa_free_all_edge_args (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *cs;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
{
|
||||
free (cs->aux);
|
||||
cs->aux = NULL;
|
||||
}
|
||||
if (cs->aux)
|
||||
{
|
||||
if (IPA_EDGE_REF (cs)->jump_functions)
|
||||
free (IPA_EDGE_REF (cs)->jump_functions);
|
||||
free (cs->aux);
|
||||
cs->aux = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free ipa data structures of ipa_node and ipa_edge. */
|
||||
/* Free ipa data structures of ipa_node_params and ipa_edge_args. */
|
||||
void
|
||||
ipa_free (void)
|
||||
ipa_free_all_node_params (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *cs;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
if (node->aux == NULL)
|
||||
continue;
|
||||
if (IPA_NODE_REF (node)->ipcp_cval)
|
||||
free (IPA_NODE_REF (node)->ipcp_cval);
|
||||
if (IPA_NODE_REF (node)->ipa_param_tree)
|
||||
free (IPA_NODE_REF (node)->ipa_param_tree);
|
||||
if (IPA_NODE_REF (node)->ipa_mod)
|
||||
free (IPA_NODE_REF (node)->ipa_mod);
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
{
|
||||
if (cs->aux)
|
||||
if (IPA_EDGE_REF (cs)->ipa_param_map)
|
||||
free (IPA_EDGE_REF (cs)->ipa_param_map);
|
||||
}
|
||||
if (IPA_NODE_REF (node)->ipcp_lattices)
|
||||
free (IPA_NODE_REF (node)->ipcp_lattices);
|
||||
if (IPA_NODE_REF (node)->param_decls)
|
||||
free (IPA_NODE_REF (node)->param_decls);
|
||||
if (IPA_NODE_REF (node)->modified_flags)
|
||||
free (IPA_NODE_REF (node)->modified_flags);
|
||||
free (node->aux);
|
||||
node->aux = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print ipa_tree_map data structures of all methods in the
|
||||
/* Print ipa_tree_map data structures of all functions in the
|
||||
callgraph to F. */
|
||||
void
|
||||
ipa_method_tree_print (FILE * f)
|
||||
ipa_print_all_tree_maps (FILE * f)
|
||||
{
|
||||
int i, count;
|
||||
tree temp;
|
||||
@ -622,11 +398,12 @@ ipa_method_tree_print (FILE * f)
|
||||
fprintf (f, "\nPARAM TREE MAP PRINT\n");
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
fprintf (f, "method %s Trees :: \n", cgraph_node_name (node));
|
||||
count = ipa_method_formal_count (node);
|
||||
struct ipa_node_params *info = IPA_NODE_REF (node);
|
||||
fprintf (f, "function %s Trees :: \n", cgraph_node_name (node));
|
||||
count = ipa_get_param_count (info);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
temp = ipa_method_get_tree (node, i);
|
||||
temp = ipa_get_ith_param (info, i);
|
||||
if (TREE_CODE (temp) == PARM_DECL)
|
||||
fprintf (f, " param [%d] : %s\n", i,
|
||||
(*lang_hooks.decl_printable_name) (temp, 2));
|
||||
@ -635,10 +412,10 @@ ipa_method_tree_print (FILE * f)
|
||||
}
|
||||
}
|
||||
|
||||
/* Print ipa_modify data structures of all methods in the
|
||||
/* Print modified_flags data structures of all functions in the
|
||||
callgraph to F. */
|
||||
void
|
||||
ipa_method_modify_print (FILE * f)
|
||||
ipa_print_all_params_modified (FILE * f)
|
||||
{
|
||||
int i, count;
|
||||
bool temp;
|
||||
@ -647,11 +424,12 @@ ipa_method_modify_print (FILE * f)
|
||||
fprintf (f, "\nMODIFY PRINT\n");
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
fprintf (f, "method %s :: \n", cgraph_node_name (node));
|
||||
count = ipa_method_formal_count (node);
|
||||
struct ipa_node_params *info = IPA_NODE_REF (node);
|
||||
fprintf (f, "function %s :: \n", cgraph_node_name (node));
|
||||
count = ipa_get_param_count (info);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
temp = ipa_method_is_modified (node, i);
|
||||
temp = info->modified_flags[i];
|
||||
if (temp)
|
||||
fprintf (f, " param [%d] true \n", i);
|
||||
else
|
||||
@ -659,3 +437,4 @@ ipa_method_modify_print (FILE * f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
249
gcc/ipa-prop.h
249
gcc/ipa-prop.h
@ -30,43 +30,42 @@ along with GCC; see the file COPYING3. If not see
|
||||
Formal - the caller's formal parameter is passed as an actual argument.
|
||||
Constant - a constant is passed as an actual argument.
|
||||
Unknown - neither of the above.
|
||||
Integer and real constants are represented as CONST_IPATYPE and Fortran
|
||||
constants are represented as CONST_IPATYPE_REF. */
|
||||
Integer and real constants are represented as IPA_CONST and Fortran
|
||||
constants are represented as IPA_CONST_REF. */
|
||||
enum jump_func_type
|
||||
{
|
||||
UNKNOWN_IPATYPE,
|
||||
CONST_IPATYPE,
|
||||
CONST_IPATYPE_REF,
|
||||
FORMAL_IPATYPE
|
||||
IPA_UNKNOWN,
|
||||
IPA_CONST,
|
||||
IPA_CONST_REF,
|
||||
IPA_PASS_THROUGH
|
||||
};
|
||||
|
||||
/* All formal parameters in the program have a cval computed by
|
||||
the interprocedural stage of IPCP.
|
||||
There are three main values of cval :
|
||||
/* All formal parameters in the program have a lattice associated with it
|
||||
computed by the interprocedural stage of IPCP.
|
||||
There are three main values of the lattice:
|
||||
TOP - unknown.
|
||||
BOTTOM - non constant.
|
||||
CONSTANT_TYPE - constant value.
|
||||
Cval of formal f will have a constant value if all callsites to this
|
||||
function have the same constant value passed to f.
|
||||
Integer and real constants are represented as CONST_IPATYPE and Fortran
|
||||
constants are represented as CONST_IPATYPE_REF. */
|
||||
enum cvalue_type
|
||||
Integer and real constants are represented as IPA_CONST and Fortran
|
||||
constants are represented as IPA_CONST_REF. */
|
||||
enum ipa_lattice_type
|
||||
{
|
||||
BOTTOM,
|
||||
CONST_VALUE,
|
||||
CONST_VALUE_REF,
|
||||
TOP
|
||||
IPA_BOTTOM,
|
||||
IPA_CONST_VALUE,
|
||||
IPA_CONST_VALUE_REF,
|
||||
IPA_TOP
|
||||
};
|
||||
|
||||
/* Represents the value of either jump function or cval.
|
||||
/* Represents a value of a jump function.
|
||||
value represents a constant.
|
||||
formal_id is used only in jump function context and represents
|
||||
pass-through parameter (the formal of caller is passed
|
||||
as argument). */
|
||||
union parameter_info
|
||||
pass-through parameter (the formal of caller is passed as argument). */
|
||||
union jump_func_value
|
||||
{
|
||||
unsigned int formal_id;
|
||||
tree value;
|
||||
tree constant;
|
||||
};
|
||||
|
||||
/* A jump function for a callsite represents the values passed as actual
|
||||
@ -75,16 +74,16 @@ union parameter_info
|
||||
struct ipa_jump_func
|
||||
{
|
||||
enum jump_func_type type;
|
||||
union parameter_info info_type;
|
||||
union jump_func_value value;
|
||||
};
|
||||
|
||||
/* All formal parameters in the program have a cval computed by
|
||||
the interprocedural stage of IPCP. See enum cvalue_type for
|
||||
the various types of cvals supported */
|
||||
struct ipcp_formal
|
||||
the interprocedural stage of IPCP. See enum ipa_lattice_type for
|
||||
the various types of lattices supported */
|
||||
struct ipcp_lattice
|
||||
{
|
||||
enum cvalue_type cval_type;
|
||||
union parameter_info cvalue;
|
||||
enum ipa_lattice_type type;
|
||||
tree constant;
|
||||
};
|
||||
|
||||
/* Represent which DECL tree (or reference to such tree)
|
||||
@ -102,103 +101,165 @@ struct ipa_replace_map
|
||||
};
|
||||
|
||||
/* Return the field in cgraph_node/cgraph_edge struct that points
|
||||
to ipa_node/ipa_edge struct. */
|
||||
#define IPA_NODE_REF(MT) ((struct ipa_node *)(MT)->aux)
|
||||
#define IPA_EDGE_REF(EDGE) ((struct ipa_edge *)(EDGE)->aux)
|
||||
to ipa_node_params/ipa_edge_args struct. */
|
||||
#define IPA_NODE_REF(MT) ((struct ipa_node_params *)(MT)->aux)
|
||||
#define IPA_EDGE_REF(EDGE) ((struct ipa_edge_args *)(EDGE)->aux)
|
||||
/* This macro checks validity of index returned by
|
||||
ipa_method_tree_map function. */
|
||||
#define IS_VALID_TREE_MAP_INDEX(I) ((I) != -1)
|
||||
ipa_get_param_decl_index function. */
|
||||
#define IS_VALID_JUMP_FUNC_INDEX(I) ((I) != -1)
|
||||
|
||||
/* ipa_node stores information related to a method and
|
||||
its formal parameters. It is pointed to by a field in the
|
||||
method's corresponding cgraph_node.
|
||||
/* ipa_node_params stores information related to formal parameters of functions
|
||||
and some other information for interprocedural passes that operate on
|
||||
parameters (such as ipa-cp). */
|
||||
|
||||
ipa_edge stores information related to a callsite and
|
||||
its arguments. It is pointed to by a field in the
|
||||
callsite's corresponding cgraph_edge. */
|
||||
struct ipa_node
|
||||
struct ipa_node_params
|
||||
{
|
||||
/* Number of formal parameters of this method. When set to 0,
|
||||
this method's parameters would not be analyzed by the different
|
||||
/* Number of formal parameters of this function. When set to 0,
|
||||
this functions's parameters would not be analyzed by the different
|
||||
stages of IPA CP. */
|
||||
int ipa_arg_num;
|
||||
/* Array of cvals. */
|
||||
struct ipcp_formal *ipcp_cval;
|
||||
int param_count;
|
||||
/* Array of lattices. */
|
||||
struct ipcp_lattice *ipcp_lattices;
|
||||
/* Mapping each parameter to its PARM_DECL tree. */
|
||||
tree *ipa_param_tree;
|
||||
/* Indicating which parameter is modified in its method. */
|
||||
bool *ipa_mod;
|
||||
tree *param_decls;
|
||||
/* Indicating which parameter is modified in its function. */
|
||||
bool *modified_flags;
|
||||
/* Only for versioned nodes this field would not be NULL,
|
||||
it points to the node that IPA cp cloned from. */
|
||||
struct cgraph_node *ipcp_orig_node;
|
||||
/* Meaningful only for original methods. Expresses the
|
||||
/* Meaningful only for original functions. Expresses the
|
||||
ratio between the direct calls and sum of all invocations of
|
||||
this function (given by profiling info). It is used to calculate
|
||||
the profiling information of the original function and the versioned
|
||||
one. */
|
||||
gcov_type count_scale;
|
||||
|
||||
/* Whether this fynction is called with variable number of actual
|
||||
arguments. */
|
||||
unsigned called_with_var_arguments : 1;
|
||||
};
|
||||
|
||||
struct ipa_edge
|
||||
/* ipa_node_params access functions. Please use these to access fields that
|
||||
are or will be shared among various passes. */
|
||||
|
||||
/* Set the number of formal parameters. */
|
||||
static inline void
|
||||
ipa_set_param_count (struct ipa_node_params *info, int count)
|
||||
{
|
||||
info->param_count = count;
|
||||
}
|
||||
|
||||
/* Return the number of formal parameters. */
|
||||
static inline int
|
||||
ipa_get_param_count (struct ipa_node_params *info)
|
||||
{
|
||||
return info->param_count;
|
||||
}
|
||||
|
||||
/* Returns the declaration of ith param of the corresponding node. Note there
|
||||
is no setter function as this array is built just once using
|
||||
ipa_create_param_decls_array. */
|
||||
static inline tree
|
||||
ipa_get_ith_param (struct ipa_node_params *info, int i)
|
||||
{
|
||||
return info->param_decls[i];
|
||||
}
|
||||
|
||||
/* Returns the modification flag corresponding o the ith paramterer. Note
|
||||
there is no setter method as the goal is to set all flags when building the
|
||||
array in ipa_detect_param_modifications. */
|
||||
static inline bool
|
||||
ipa_is_ith_param_modified (struct ipa_node_params *info, int i)
|
||||
{
|
||||
return info->modified_flags[i];
|
||||
}
|
||||
|
||||
/* Flag this node as having callers with variable number of arguments. */
|
||||
static inline void
|
||||
ipa_set_called_with_variable_arg (struct ipa_node_params *info)
|
||||
{
|
||||
info->called_with_var_arguments = 1;
|
||||
}
|
||||
|
||||
/* Have we detected this node was called with variable number of arguments? */
|
||||
static inline bool
|
||||
ipa_is_called_with_var_arguments (struct ipa_node_params *info)
|
||||
{
|
||||
return info->called_with_var_arguments;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ipa_edge_args stores information related to a callsite and particularly
|
||||
its arguments. It is pointed to by a field in the
|
||||
callsite's corresponding cgraph_edge. */
|
||||
struct ipa_edge_args
|
||||
{
|
||||
/* Number of actual arguments in this callsite. When set to 0,
|
||||
this callsite's parameters would not be analyzed by the different
|
||||
stages of IPA CP. */
|
||||
int ipa_param_num;
|
||||
int argument_count;
|
||||
/* Array of the callsite's jump function of each parameter. */
|
||||
struct ipa_jump_func *ipa_param_map;
|
||||
struct ipa_jump_func *jump_functions;
|
||||
};
|
||||
|
||||
/* A methodlist element (referred to also as methodlist node). It is used
|
||||
to create a temporary worklist used in
|
||||
the propagation stage of IPCP. (can be used for more IPA
|
||||
optimizations) */
|
||||
struct ipa_methodlist
|
||||
/* ipa_edge_args access functions. Please use these to access fields that
|
||||
are or will be shared among various passes. */
|
||||
|
||||
/* Set the number of actual arguments. */
|
||||
static inline void
|
||||
ipa_set_cs_argument_count (struct ipa_edge_args *args, int count)
|
||||
{
|
||||
struct cgraph_node *method_p;
|
||||
struct ipa_methodlist *next_method;
|
||||
args->argument_count = count;
|
||||
}
|
||||
|
||||
/* Return the number of actual arguments. */
|
||||
static inline int
|
||||
ipa_get_cs_argument_count (struct ipa_edge_args *args)
|
||||
{
|
||||
return args->argument_count;
|
||||
}
|
||||
|
||||
/* Returns a pointer to the jump function for the ith argument. Please note
|
||||
there is no setter function as jump functions are all set up in
|
||||
ipa_compute_jump_functions. */
|
||||
static inline struct ipa_jump_func *
|
||||
ipa_get_ith_jump_func (struct ipa_edge_args *args, int i)
|
||||
{
|
||||
return &args->jump_functions[i];
|
||||
}
|
||||
|
||||
/* A function list element. It is used to create a temporary worklist used in
|
||||
the propagation stage of IPCP. (can be used for more IPA optimizations) */
|
||||
struct ipa_func_list
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct ipa_func_list *next;
|
||||
};
|
||||
|
||||
/* A pointer to a methodlist element. */
|
||||
typedef struct ipa_methodlist *ipa_methodlist_p;
|
||||
/* ipa_func_list interface. */
|
||||
struct ipa_func_list *ipa_init_func_list (void);
|
||||
void ipa_push_func_to_list (struct ipa_func_list **, struct cgraph_node *);
|
||||
struct cgraph_node *ipa_pop_func_from_list (struct ipa_func_list **);
|
||||
|
||||
/* ipa_methodlist interface. */
|
||||
ipa_methodlist_p ipa_methodlist_init (void);
|
||||
bool ipa_methodlist_not_empty (ipa_methodlist_p);
|
||||
void ipa_add_method (ipa_methodlist_p *, struct cgraph_node *);
|
||||
struct cgraph_node *ipa_remove_method (ipa_methodlist_p *);
|
||||
/* Callsite related calculations. */
|
||||
void ipa_compute_jump_functions (struct cgraph_edge *);
|
||||
void ipa_count_arguments (struct cgraph_edge *);
|
||||
|
||||
/* ipa_callsite interface. */
|
||||
int ipa_callsite_param_count (struct cgraph_edge *);
|
||||
void ipa_callsite_param_count_set (struct cgraph_edge *, int);
|
||||
struct ipa_jump_func *ipa_callsite_param (struct cgraph_edge *, int);
|
||||
struct cgraph_node *ipa_callsite_callee (struct cgraph_edge *);
|
||||
void ipa_callsite_compute_param (struct cgraph_edge *);
|
||||
void ipa_callsite_compute_count (struct cgraph_edge *);
|
||||
|
||||
/* ipa_method interface. */
|
||||
int ipa_method_formal_count (struct cgraph_node *);
|
||||
void ipa_method_formal_count_set (struct cgraph_node *, int);
|
||||
tree ipa_method_get_tree (struct cgraph_node *, int);
|
||||
void ipa_method_compute_tree_map (struct cgraph_node *);
|
||||
void ipa_method_formal_compute_count (struct cgraph_node *);
|
||||
void ipa_method_compute_modify (struct cgraph_node *);
|
||||
|
||||
/* jump function interface. */
|
||||
enum jump_func_type get_type (struct ipa_jump_func *);
|
||||
union parameter_info *ipa_jf_get_info_type (struct ipa_jump_func *);
|
||||
|
||||
/* ipa_node and ipa_edge interfaces. */
|
||||
void ipa_node_create (struct cgraph_node *);
|
||||
void ipa_free (void);
|
||||
void ipa_nodes_create (void);
|
||||
void ipa_edges_create (void);
|
||||
void ipa_edges_free (void);
|
||||
void ipa_nodes_free (void);
|
||||
/* Function parameters related computations. */
|
||||
void ipa_count_formal_params (struct cgraph_node *);
|
||||
void ipa_create_param_decls_array (struct cgraph_node *);
|
||||
void ipa_detect_param_modifications (struct cgraph_node *);
|
||||
|
||||
/* Creating and freeing ipa_node_params and ipa_edge_args. */
|
||||
void ipa_create_node_params (struct cgraph_node *);
|
||||
void ipa_free_all_node_params (void);
|
||||
void ipa_create_all_node_params (void);
|
||||
void ipa_create_all_edge_args (void);
|
||||
void ipa_free_all_edge_args (void);
|
||||
|
||||
/* Debugging interface. */
|
||||
void ipa_method_tree_print (FILE *);
|
||||
void ipa_method_modify_print (FILE *);
|
||||
void ipa_print_all_tree_maps (FILE *);
|
||||
void ipa_print_all_params_modified (FILE *);
|
||||
|
||||
#endif /* IPA_PROP_H */
|
||||
|
Loading…
Reference in New Issue
Block a user