Commit dcd416e3 by Martin Jambor

ipa-cp.c (ipcp_init_stage): Calls ipa_set_called_with_variable_arg instead of…

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
parent d7996732
...@@ -72,7 +72,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -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 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) 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). (defined in ipa_prop.h and pointed to by cgraph_edge->aux).
-ipcp_init_stage() is the first stage driver. -ipcp_init_stage() is the first stage driver.
...@@ -89,7 +89,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -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 Cval of formal f will have a constant value if all callsites to this
function have the same constant value passed to f. 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). (defined in ipa_prop.h and pointed to by cgraph_edge->aux).
-ipcp_iterate_stage() is the second stage driver. -ipcp_iterate_stage() is the second stage driver.
...@@ -145,7 +145,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -145,7 +145,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-dump.h" #include "tree-dump.h"
#include "tree-inline.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 * static inline struct cgraph_node *
ipcp_method_orig_node (struct cgraph_node *mt) ipcp_method_orig_node (struct cgraph_node *mt)
{ {
...@@ -173,17 +173,17 @@ static void ...@@ -173,17 +173,17 @@ static void
ipcp_cloned_create (struct cgraph_node *orig_node, ipcp_cloned_create (struct cgraph_node *orig_node,
struct cgraph_node *new_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); ipcp_method_set_orig_node (new_node, orig_node);
ipa_method_formal_compute_count (new_node); ipa_count_formal_params (new_node);
ipa_method_compute_tree_map (new_node); ipa_create_param_decls_array (new_node);
} }
/* Return cval_type field of CVAL. */ /* Return cval_type field of CVAL. */
static inline enum cvalue_type static inline enum ipa_lattice_type
ipcp_cval_get_cvalue_type (struct ipcp_formal *cval) ipcp_cval_get_cvalue_type (struct ipcp_lattice *cval)
{ {
return cval->cval_type; return cval->type;
} }
/* Return scale for MT. */ /* Return scale for MT. */
...@@ -202,32 +202,32 @@ ipcp_method_set_scale (struct cgraph_node *node, gcov_type count) ...@@ -202,32 +202,32 @@ ipcp_method_set_scale (struct cgraph_node *node, gcov_type count)
/* Set TYPE as cval_type field of CVAL. */ /* Set TYPE as cval_type field of CVAL. */
static inline void 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. */ /* Return cvalue field of CVAL. */
static inline union parameter_info * static inline tree
ipcp_cval_get_cvalue (struct ipcp_formal *cval) ipcp_cval_get_cvalue (struct ipcp_lattice *cval)
{ {
return &(cval->cvalue); return cval->constant;
} }
/* Set VALUE as cvalue field CVAL. */ /* Set VALUE as cvalue field CVAL. */
static inline void static inline void
ipcp_cval_set_cvalue (struct ipcp_formal *cval, union parameter_info *value, ipcp_cval_set_cvalue (struct ipcp_lattice *cval, tree value,
enum cvalue_type type) enum ipa_lattice_type type)
{ {
if (type == CONST_VALUE || type == CONST_VALUE_REF) if (type == IPA_CONST_VALUE || type == IPA_CONST_VALUE_REF)
cval->cvalue.value = value->value; cval->constant = value;
} }
/* Return whether TYPE is a constant type. */ /* Return whether TYPE is a constant type. */
static bool 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; return true;
else else
return false; return false;
...@@ -235,43 +235,43 @@ ipcp_type_is_const (enum cvalue_type type) ...@@ -235,43 +235,43 @@ ipcp_type_is_const (enum cvalue_type type)
/* Return true if CONST_VAL1 and CONST_VAL2 are equal. */ /* Return true if CONST_VAL1 and CONST_VAL2 are equal. */
static inline bool static inline bool
ipcp_cval_equal_cvalues (union parameter_info *const_val1, ipcp_cval_equal_cvalues (tree const_val1, tree const_val2,
union parameter_info *const_val2, enum ipa_lattice_type type1,
enum cvalue_type type1, enum cvalue_type type2) enum ipa_lattice_type type2)
{ {
gcc_assert (ipcp_type_is_const (type1) && ipcp_type_is_const (type2)); gcc_assert (ipcp_type_is_const (type1) && ipcp_type_is_const (type2));
if (type1 != type2) if (type1 != type2)
return false; 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 true;
return false; return false;
} }
/* Compute Meet arithmetics: /* Compute Meet arithmetics:
Meet (BOTTOM, x) = BOTTOM Meet (IPA_BOTTOM, x) = IPA_BOTTOM
Meet (TOP,x) = x Meet (IPA_TOP,x) = x
Meet (const_a,const_b) = BOTTOM, if const_a != const_b. Meet (const_a,const_b) = IPA_BOTTOM, if const_a != const_b.
MEET (const_a,const_b) = const_a, if const_a == const_b.*/ MEET (const_a,const_b) = const_a, if const_a == const_b.*/
static void static void
ipcp_cval_meet (struct ipcp_formal *cval, struct ipcp_formal *cval1, ipcp_cval_meet (struct ipcp_lattice *cval, struct ipcp_lattice *cval1,
struct ipcp_formal *cval2) struct ipcp_lattice *cval2)
{ {
if (ipcp_cval_get_cvalue_type (cval1) == BOTTOM if (ipcp_cval_get_cvalue_type (cval1) == IPA_BOTTOM
|| ipcp_cval_get_cvalue_type (cval2) == 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; 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_type (cval, ipcp_cval_get_cvalue_type (cval2));
ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval2), ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval2),
ipcp_cval_get_cvalue_type (cval2)); ipcp_cval_get_cvalue_type (cval2));
return; 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_type (cval, ipcp_cval_get_cvalue_type (cval1));
ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (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, ...@@ -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 (cval1),
ipcp_cval_get_cvalue_type (cval2))) ipcp_cval_get_cvalue_type (cval2)))
{ {
ipcp_cval_set_cvalue_type (cval, BOTTOM); ipcp_cval_set_cvalue_type (cval, IPA_BOTTOM);
return; return;
} }
ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1)); 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, ...@@ -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. */ /* 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) 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. /* 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 If TYPE is FORMAL_IPA_TYPE, the cval of the corresponding formal is
drawn from MT. */ drawn from MT. */
static void static void
ipcp_cval_compute (struct ipcp_formal *cval, struct cgraph_node *mt, ipcp_cval_compute (struct ipcp_lattice *cval, struct cgraph_node *mt,
enum jump_func_type type, union parameter_info *info_type) enum jump_func_type type,
union jump_func_value *info_type)
{ {
if (type == UNKNOWN_IPATYPE) if (type == IPA_UNKNOWN)
ipcp_cval_set_cvalue_type (cval, BOTTOM); ipcp_cval_set_cvalue_type (cval, IPA_BOTTOM);
else if (type == CONST_IPATYPE) else if (type == IPA_CONST)
{ {
ipcp_cval_set_cvalue_type (cval, CONST_VALUE); ipcp_cval_set_cvalue_type (cval, IPA_CONST_VALUE);
ipcp_cval_set_cvalue (cval, info_type, 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_type (cval, IPA_CONST_VALUE_REF);
ipcp_cval_set_cvalue (cval, info_type, 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 ipcp_cval_get_cvalue_type (ipcp_method_cval
(mt, info_type->formal_id)); (mt, info_type->formal_id));
ipcp_cval_set_cvalue_type (cval, type); ipcp_cval_set_cvalue_type (cval, type);
...@@ -332,12 +333,12 @@ ipcp_cval_compute (struct ipcp_formal *cval, struct cgraph_node *mt, ...@@ -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. */ /* True when CVAL1 and CVAL2 values are not the same. */
static bool 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) == ipcp_cval_get_cvalue_type (cval2))
{ {
if (ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE && if (ipcp_cval_get_cvalue_type (cval1) != IPA_CONST_VALUE
ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE_REF) && ipcp_cval_get_cvalue_type (cval1) != IPA_CONST_VALUE_REF)
return false; return false;
if (ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1), if (ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1),
ipcp_cval_get_cvalue (cval2), ipcp_cval_get_cvalue (cval2),
...@@ -352,25 +353,33 @@ ipcp_cval_changed (struct ipcp_formal *cval1, struct ipcp_formal *cval2) ...@@ -352,25 +353,33 @@ ipcp_cval_changed (struct ipcp_formal *cval1, struct ipcp_formal *cval2)
static inline void static inline void
ipcp_formal_create (struct cgraph_node *mt) ipcp_formal_create (struct cgraph_node *mt)
{ {
IPA_NODE_REF (mt)->ipcp_cval = IPA_NODE_REF (mt)->ipcp_lattices =
XCNEWVEC (struct ipcp_formal, ipa_method_formal_count (mt)); XCNEWVEC (struct ipcp_lattice, ipa_get_param_count (IPA_NODE_REF (mt)));
} }
/* Set cval structure of I-th formal of MT to CVAL. */ /* Set cval structure of I-th formal of MT to CVAL. */
static inline void 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_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. */ /* Set type of cval structure of formal I of MT to CVAL_TYPE1. */
static inline void static inline void
ipcp_method_cval_set_cvalue_type (struct cgraph_node *mt, int i, 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. */ /* Print ipcp_cval data structures to F. */
...@@ -385,22 +394,22 @@ ipcp_method_cval_print (FILE * f) ...@@ -385,22 +394,22 @@ ipcp_method_cval_print (FILE * f)
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
fprintf (f, "Printing cvals %s:\n", cgraph_node_name (node)); 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++) for (i = 0; i < count; i++)
{ {
if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, 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)) == || ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) ==
CONST_VALUE_REF) IPA_CONST_VALUE_REF)
{ {
fprintf (f, " param [%d]: ", i); fprintf (f, " param [%d]: ", i);
fprintf (f, "type is CONST "); fprintf (f, "type is CONST ");
cvalue = 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); print_generic_expr (f, cvalue, 0);
fprintf (f, "\n"); 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); fprintf (f, "param [%d]: type is TOP \n", i);
else else
fprintf (f, "param [%d]: type is BOTTOM \n", i); fprintf (f, "param [%d]: type is BOTTOM \n", i);
...@@ -408,12 +417,12 @@ ipcp_method_cval_print (FILE * f) ...@@ -408,12 +417,12 @@ ipcp_method_cval_print (FILE * f)
} }
} }
/* Initialize ipcp_cval array of MT with TOP values. /* Initialize ipcp_cval array of MT with IPA_TOP values.
All cvals for a method's formal parameters are initialized to BOTTOM All cvals for a method's formal parameters are initialized to IPA_BOTTOM
The currently supported types are integer types, real types and The currently supported types are integer types, real types and
Fortran constants (i.e. references to constants defined as Fortran constants (i.e. references to constants defined as
const_decls). All other types are not analyzed and therefore are const_decls). All other types are not analyzed and therefore are
assigned with BOTTOM. */ assigned with IPA_BOTTOM. */
static void static void
ipcp_method_cval_init (struct cgraph_node *mt) ipcp_method_cval_init (struct cgraph_node *mt)
{ {
...@@ -421,15 +430,15 @@ ipcp_method_cval_init (struct cgraph_node *mt) ...@@ -421,15 +430,15 @@ ipcp_method_cval_init (struct cgraph_node *mt)
tree parm_tree; tree parm_tree;
ipcp_formal_create (mt); 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)) if (INTEGRAL_TYPE_P (TREE_TYPE (parm_tree))
|| SCALAR_FLOAT_TYPE_P (TREE_TYPE (parm_tree)) || SCALAR_FLOAT_TYPE_P (TREE_TYPE (parm_tree))
|| POINTER_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 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) ...@@ -456,13 +465,12 @@ constant_val_insert (tree parm1, tree val)
/* build INTEGER_CST tree with type TREE_TYPE and /* build INTEGER_CST tree with type TREE_TYPE and
value according to CVALUE. Return the tree. */ value according to CVALUE. Return the tree. */
static tree static tree
build_const_val (union parameter_info *cvalue, enum cvalue_type type, build_const_val (tree cvalue, enum ipa_lattice_type type, tree tree_type)
tree tree_type)
{ {
tree const_val = NULL; tree const_val = NULL;
gcc_assert (ipcp_type_is_const (type)); 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; return const_val;
} }
...@@ -470,14 +478,14 @@ build_const_val (union parameter_info *cvalue, enum cvalue_type type, ...@@ -470,14 +478,14 @@ build_const_val (union parameter_info *cvalue, enum cvalue_type type,
constant_val_insert(). */ constant_val_insert(). */
static void static void
ipcp_propagate_const (struct cgraph_node *mt, int param, 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 const_val;
tree parm_tree; tree parm_tree;
if (dump_file) if (dump_file)
fprintf (dump_file, "propagating const to %s\n", cgraph_node_name (mt)); 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)); const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree));
constant_val_insert (parm_tree, const_val); constant_val_insert (parm_tree, const_val);
} }
...@@ -514,10 +522,10 @@ ipcp_init_stage (void) ...@@ -514,10 +522,10 @@ ipcp_init_stage (void)
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
ipa_method_formal_compute_count (node); ipa_count_formal_params (node);
ipa_method_compute_tree_map (node); ipa_create_param_decls_array (node);
ipcp_method_cval_init (node); ipcp_method_cval_init (node);
ipa_method_compute_modify (node); ipa_detect_param_modifications (node);
ipcp_method_compute_scale (node); ipcp_method_compute_scale (node);
} }
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
...@@ -525,23 +533,22 @@ ipcp_init_stage (void) ...@@ -525,23 +533,22 @@ ipcp_init_stage (void)
/* building jump functions */ /* building jump functions */
for (cs = node->callees; cs; cs = cs->next_callee) for (cs = node->callees; cs; cs = cs->next_callee)
{ {
ipa_callsite_compute_count (cs); ipa_count_arguments (cs);
if (ipa_callsite_param_count (cs) if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
!= ipa_method_formal_count (cs->callee)) != ipa_get_param_count (IPA_NODE_REF (cs->callee)))
{ {
/* Handle cases of functions with /* Handle cases of functions with
a variable number of parameters. */ a variable number of parameters. */
ipa_callsite_param_count_set (cs, 0); ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee));
ipa_method_formal_count_set (cs->callee, 0);
} }
else else
ipa_callsite_compute_param (cs); ipa_compute_jump_functions (cs);
} }
} }
} }
/* Return true if there are some formal parameters whose value is TOP. /* Return true if there are some formal parameters whose value is IPA_TOP.
Change their values to BOTTOM, since they weren't determined. */ Change their values to IPA_BOTTOM, since they weren't determined. */
static bool static bool
ipcp_after_propagate (void) ipcp_after_propagate (void)
{ {
...@@ -552,12 +559,12 @@ ipcp_after_propagate (void) ...@@ -552,12 +559,12 @@ ipcp_after_propagate (void)
prop_again = false; prop_again = false;
for (node = cgraph_nodes; node; node = node->next) 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++) 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; 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; return prop_again;
...@@ -569,37 +576,39 @@ static void ...@@ -569,37 +576,39 @@ static void
ipcp_propagate_stage (void) ipcp_propagate_stage (void)
{ {
int i; int i;
struct ipcp_formal cval1 = { BOTTOM, {0} }, cval = { BOTTOM, {0} }; struct ipcp_lattice cval1 = { IPA_BOTTOM, NULL }, cval = { IPA_BOTTOM, NULL };
struct ipcp_formal *cval2; struct ipcp_lattice *cval2;
struct cgraph_node *mt, *callee; struct cgraph_node *mt, *callee;
struct cgraph_edge *cs; struct cgraph_edge *cs;
struct ipa_jump_func *jump_func; struct ipa_jump_func *jump_func;
enum jump_func_type type; enum jump_func_type type;
union parameter_info *info_type; union jump_func_value *jf_value;
ipa_methodlist_p wl; struct ipa_func_list *wl;
int count; int count;
/* Initialize worklist to contain all methods. */ /* Initialize worklist to contain all functions. */
wl = ipa_methodlist_init (); wl = ipa_init_func_list ();
while (ipa_methodlist_not_empty (wl)) while (wl)
{ {
mt = ipa_remove_method (&wl); mt = ipa_pop_func_from_list (&wl);
for (cs = mt->callees; cs; cs = cs->next_callee) for (cs = mt->callees; cs; cs = cs->next_callee)
{ {
callee = ipa_callsite_callee (cs); callee = cs->callee;
count = ipa_callsite_param_count (cs); 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++) for (i = 0; i < count; i++)
{ {
jump_func = ipa_callsite_param (cs, i); jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
type = get_type (jump_func); type = jump_func->type;
info_type = ipa_jf_get_info_type (jump_func); jf_value = &jump_func->value;
ipcp_cval_compute (&cval1, mt, type, info_type); ipcp_cval_compute (&cval1, mt, type, jf_value);
cval2 = ipcp_method_cval (callee, i); cval2 = ipcp_method_cval (callee, i);
ipcp_cval_meet (&cval, &cval1, cval2); ipcp_cval_meet (&cval, &cval1, cval2);
if (ipcp_cval_changed (&cval, cval2)) if (ipcp_cval_changed (&cval, cval2))
{ {
ipcp_method_cval_set (callee, i, &cval); 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) ...@@ -613,7 +622,7 @@ ipcp_iterate_stage (void)
{ {
ipcp_propagate_stage (); ipcp_propagate_stage ();
if (ipcp_after_propagate ()) 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. */ This change should be propagated. */
ipcp_propagate_stage (); ipcp_propagate_stage ();
} }
...@@ -646,27 +655,30 @@ ipcp_callsite_param_print (FILE * f) ...@@ -646,27 +655,30 @@ ipcp_callsite_param_print (FILE * f)
{ {
fprintf (f, "callsite %s ", cgraph_node_name (node)); fprintf (f, "callsite %s ", cgraph_node_name (node));
fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee)); 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++) for (i = 0; i < count; i++)
{ {
jump_func = ipa_callsite_param (cs, i); jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
type = get_type (jump_func); type = jump_func->type;
fprintf (f, " param %d: ", i); fprintf (f, " param %d: ", i);
if (type == UNKNOWN_IPATYPE) if (type == IPA_UNKNOWN)
fprintf (f, "UNKNOWN\n"); 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 : "); fprintf (f, "CONST : ");
print_generic_expr (f, info_type, 0); print_generic_expr (f, info_type, 0);
fprintf (f, "\n"); fprintf (f, "\n");
} }
else if (type == FORMAL_IPATYPE) else if (type == IPA_PASS_THROUGH)
{ {
fprintf (f, "FORMAL : "); fprintf (f, "PASS THROUGH : ");
fprintf (f, "%d\n", fprintf (f, "%d\n", jump_func->value.formal_id);
ipa_jf_get_info_type (jump_func)->formal_id);
} }
} }
} }
...@@ -818,8 +830,8 @@ ipcp_structures_print (FILE * f) ...@@ -818,8 +830,8 @@ ipcp_structures_print (FILE * f)
{ {
ipcp_method_cval_print (f); ipcp_method_cval_print (f);
ipcp_method_scale_print (f); ipcp_method_scale_print (f);
ipa_method_tree_print (f); ipa_print_all_tree_maps (f);
ipa_method_modify_print (f); ipa_print_all_params_modified (f);
ipcp_callsite_param_print (f); ipcp_callsite_param_print (f);
} }
...@@ -842,15 +854,15 @@ ipcp_profile_print (FILE * f) ...@@ -842,15 +854,15 @@ ipcp_profile_print (FILE * f)
operates according to the flags sent. PARM_TREE is the operates according to the flags sent. PARM_TREE is the
formal's tree found to be constant. CVALUE represents the constant. */ formal's tree found to be constant. CVALUE represents the constant. */
static struct ipa_replace_map * static struct ipa_replace_map *
ipcp_replace_map_create (struct function *func, enum cvalue_type type, ipcp_replace_map_create (struct function *func, enum ipa_lattice_type type,
tree parm_tree, union parameter_info *cvalue) tree parm_tree, tree cvalue)
{ {
struct ipa_replace_map *replace_map; struct ipa_replace_map *replace_map;
tree const_val; tree const_val;
replace_map = XCNEW (struct ipa_replace_map); replace_map = XCNEW (struct ipa_replace_map);
gcc_assert (ipcp_type_is_const (type)); 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) && is_gimple_reg (parm_tree) && gimple_default_def (func, parm_tree)
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (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) ...@@ -882,21 +894,21 @@ ipcp_redirect (struct cgraph_edge *cs)
int i, count; int i, count;
struct ipa_jump_func *jump_func; struct ipa_jump_func *jump_func;
enum jump_func_type type; enum jump_func_type type;
enum cvalue_type cval_type; enum ipa_lattice_type lattice_type;
caller = cs->caller; caller = cs->caller;
callee = cs->callee; callee = cs->callee;
orig_callee = ipcp_method_orig_node (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++) for (i = 0; i < count; i++)
{ {
cval_type = lattice_type =
ipcp_cval_get_cvalue_type (ipcp_method_cval (orig_callee, i)); 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); jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
type = get_type (jump_func); type = jump_func->type;
if (type != CONST_IPATYPE && type != CONST_IPATYPE_REF) if (type != IPA_CONST && type != IPA_CONST_REF)
return true; return true;
} }
} }
...@@ -993,23 +1005,24 @@ ipcp_insert_stage (void) ...@@ -993,23 +1005,24 @@ ipcp_insert_stage (void)
{ {
struct cgraph_node *node, *node1 = NULL; struct cgraph_node *node, *node1 = NULL;
int i, const_param; int i, const_param;
union parameter_info *cvalue; tree cvalue;
VEC (cgraph_edge_p, heap) * redirect_callers; VEC (cgraph_edge_p, heap) * redirect_callers;
varray_type replace_trees; varray_type replace_trees;
struct cgraph_edge *cs; struct cgraph_edge *cs;
int node_callers, count; int node_callers, count;
tree parm_tree; tree parm_tree;
enum cvalue_type type; enum ipa_lattice_type type;
struct ipa_replace_map *replace_param; struct ipa_replace_map *replace_param;
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
/* Propagation of the constant is forbidden in /* Propagation of the constant is forbidden in
certain conditions. */ 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; continue;
const_param = 0; const_param = 0;
count = ipa_method_formal_count (node); count = ipa_get_param_count (IPA_NODE_REF (node));
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)); type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i));
...@@ -1025,7 +1038,7 @@ ipcp_insert_stage (void) ...@@ -1025,7 +1038,7 @@ ipcp_insert_stage (void)
if (ipcp_type_is_const (type)) if (ipcp_type_is_const (type))
{ {
cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i)); 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 = replace_param =
ipcp_replace_map_create (DECL_STRUCT_FUNCTION (node->decl), ipcp_replace_map_create (DECL_STRUCT_FUNCTION (node->decl),
type, parm_tree, cvalue); type, parm_tree, cvalue);
...@@ -1063,8 +1076,8 @@ ipcp_insert_stage (void) ...@@ -1063,8 +1076,8 @@ ipcp_insert_stage (void)
if (ipcp_type_is_const (type)) if (ipcp_type_is_const (type))
{ {
cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i)); 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);
if (type != CONST_VALUE_REF && !is_gimple_reg (parm_tree)) if (type != IPA_CONST_VALUE_REF && !is_gimple_reg (parm_tree))
ipcp_propagate_const (node1, i, cvalue, type); ipcp_propagate_const (node1, i, cvalue, type);
} }
} }
...@@ -1093,10 +1106,10 @@ ipcp_driver (void) ...@@ -1093,10 +1106,10 @@ ipcp_driver (void)
{ {
if (dump_file) if (dump_file)
fprintf (dump_file, "\nIPA constant propagation start:\n"); fprintf (dump_file, "\nIPA constant propagation start:\n");
ipa_nodes_create (); ipa_create_all_node_params ();
ipa_edges_create (); ipa_create_all_edge_args ();
/* 1. Call the init stage to initialize /* 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 (); ipcp_init_stage ();
if (dump_file) if (dump_file)
{ {
...@@ -1120,9 +1133,8 @@ ipcp_driver (void) ...@@ -1120,9 +1133,8 @@ ipcp_driver (void)
ipcp_profile_print (dump_file); ipcp_profile_print (dump_file);
} }
/* Free all IPCP structures. */ /* Free all IPCP structures. */
ipa_free (); ipa_free_all_node_params ();
ipa_nodes_free (); ipa_free_all_edge_args ();
ipa_edges_free ();
if (dump_file) if (dump_file)
fprintf (dump_file, "\nIPA constant propagation end\n"); fprintf (dump_file, "\nIPA constant propagation end\n");
cgraph_remove_unreachable_nodes (true, NULL); cgraph_remove_unreachable_nodes (true, NULL);
......
...@@ -31,197 +31,88 @@ along with GCC; see the file COPYING3. If not see ...@@ -31,197 +31,88 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h" #include "flags.h"
#include "timevar.h" #include "timevar.h"
/* This file contains interfaces that can be used for various IPA /* Initialize worklist to contain all functions. */
optimizations: struct ipa_func_list *
ipa_init_func_list (void)
- 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)
{ {
struct cgraph_node *node; struct cgraph_node *node;
ipa_methodlist_p wl; struct ipa_func_list * wl;
wl = NULL; wl = NULL;
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
ipa_add_method (&wl, node); ipa_push_func_to_list (&wl, node);
return wl; 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. */ to point to MT. */
void 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 (); temp = xcalloc (1, sizeof (struct ipa_func_list));
ipa_methodlist_method_set (temp, mt); temp->node = mt;
ipa_methodlist_next_method_set (temp, *wl); temp->next = *wl;
*wl = temp; *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. */ element in the list, which is removed. */
struct cgraph_node * 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 ipa_func_list *first;
struct cgraph_node *return_method; struct cgraph_node *return_func;
first = *wl; first = *wl;
*wl = ipa_methodlist_next_method (*wl); *wl = (*wl)->next;
return_method = ipa_methodlist_method (first); return_func = first->node;
free (first); 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. */ /* Return index of the formal whose tree is ptree in function which corresponds
static inline void to info. */
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. */
static int 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; int i, count;
count = ipa_method_formal_count (mt); count = ipa_get_param_count (info);
for (i = 0; i < count; i++) 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 i;
return -1; 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 void
ipa_method_compute_tree_map (struct cgraph_node *mt) ipa_create_param_decls_array (struct cgraph_node *mt)
{ {
tree fndecl; tree fndecl;
tree fnargs; tree fnargs;
tree parm; tree parm;
int param_num; 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; fndecl = mt->decl;
fnargs = DECL_ARGUMENTS (fndecl); fnargs = DECL_ARGUMENTS (fndecl);
param_num = 0; param_num = 0;
for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) 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++; param_num++;
} }
} }
/* Count number of formals in MT. Insert the result to the /* Count number of formals in MT. Insert the result to the
ipa_node. */ ipa_node_params. */
void void
ipa_method_formal_compute_count (struct cgraph_node *mt) ipa_count_formal_params (struct cgraph_node *mt)
{ {
tree fndecl; tree fndecl;
tree fnargs; tree fnargs;
...@@ -233,57 +124,48 @@ ipa_method_formal_compute_count (struct cgraph_node *mt) ...@@ -233,57 +124,48 @@ ipa_method_formal_compute_count (struct cgraph_node *mt)
param_num = 0; param_num = 0;
for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
param_num++; 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, /* Check STMT to detect whether a formal is modified within MT, the appropriate
the appropriate entry is updated in the ipa_mod array of ipa_node entry is updated in the modified_flags array of ipa_node_params (associated
(associated with MT). */ with MT). */
static void 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; tree parm_decl;
struct ipa_node_params *info;
switch (TREE_CODE (stmt)) switch (TREE_CODE (stmt))
{ {
case GIMPLE_MODIFY_STMT: case GIMPLE_MODIFY_STMT:
if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == PARM_DECL) if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == PARM_DECL)
{ {
info = IPA_NODE_REF (mt);
parm_decl = GIMPLE_STMT_OPERAND (stmt, 0); parm_decl = GIMPLE_STMT_OPERAND (stmt, 0);
i = ipa_method_tree_map (mt, parm_decl); index = ipa_get_param_decl_index (info, parm_decl);
if (i >= 0) if (index >= 0)
ipa_method_modify_set (mt, i, true); info->modified_flags[index] = true;
} }
break; break;
case ASM_EXPR: case ASM_EXPR:
/* Asm code could modify any of the parameters. */ /* Asm code could modify any of the parameters. */
for (j = 0; j < ipa_method_formal_count (mt); j++) info = IPA_NODE_REF (mt);
ipa_method_modify_set (mt, j, true); for (j = 0; j < ipa_get_param_count (IPA_NODE_REF (mt)); j++)
info->modified_flags[j] = true;
break; break;
default: default:
break; 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 /* 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 if their address is taken, or if
they appear on the left hand side of an assignment. */ they appear on the left hand side of an assignment. */
void void
ipa_method_compute_modify (struct cgraph_node *mt) ipa_detect_param_modifications (struct cgraph_node *mt)
{ {
tree decl; tree decl;
tree body; tree body;
...@@ -292,29 +174,31 @@ ipa_method_compute_modify (struct cgraph_node *mt) ...@@ -292,29 +174,31 @@ ipa_method_compute_modify (struct cgraph_node *mt)
struct function *func; struct function *func;
block_stmt_iterator bsi; block_stmt_iterator bsi;
tree stmt, parm_tree; 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; return;
ipa_method_modify_init (mt); count = ipa_get_param_count (info);
info->modified_flags = XCNEWVEC (bool, count);
decl = mt->decl; decl = mt->decl;
count = ipa_method_formal_count (mt);
/* ??? Handle pending sizes case. Set all parameters /* ??? Handle pending sizes case. Set all parameters
of the method to be modified. */ of the function to be modified. */
if (DECL_UNINLINABLE (decl)) if (DECL_UNINLINABLE (decl))
{ {
for (j = 0; j < count; j++) for (j = 0; j < count; j++)
ipa_method_modify_set (mt, j, true); info->modified_flags[j] = true;
return; return;
} }
/* Formals whose address is taken are considered modified. */ /* Formals whose address is taken are considered modified. */
for (j = 0; j < count; j++) 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) if (!is_gimple_reg (parm_tree)
&& TREE_ADDRESSABLE (parm_tree)) && TREE_ADDRESSABLE (parm_tree))
ipa_method_modify_set (mt, j, true); info->modified_flags[j] = true;
} }
body = DECL_SAVED_TREE (decl); body = DECL_SAVED_TREE (decl);
if (body != NULL) if (body != NULL)
...@@ -325,171 +209,94 @@ ipa_method_compute_modify (struct cgraph_node *mt) ...@@ -325,171 +209,94 @@ ipa_method_compute_modify (struct cgraph_node *mt)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{ {
stmt = bsi_stmt (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 /* 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 void
ipa_callsite_compute_count (struct cgraph_edge *cs) ipa_count_arguments (struct cgraph_edge *cs)
{ {
tree call_tree; tree call_tree;
int arg_num; 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); gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
arg_num = call_expr_nargs (call_tree); 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 /* Compute jump function for all arguments of callsite CS
and insert the information in the ipa_param_map array and insert the information in the jump_functions array
in the ipa_edge corresponding to this callsite. (Explanation in the ipa_edge_args corresponding to this callsite. */
on jump functions is in ipa-prop.h). */
void void
ipa_callsite_compute_param (struct cgraph_edge *cs) ipa_compute_jump_functions (struct cgraph_edge *cs)
{ {
tree call_tree; tree call_tree;
tree arg, cst_decl; tree arg, cst_decl;
int arg_num; int arg_num;
int i;
struct cgraph_node *mt; struct cgraph_node *mt;
tree parm_decl; tree parm_decl;
struct function *curr_cfun; struct function *curr_cfun;
call_expr_arg_iterator iter; 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; return;
ipa_callsite_param_map_create (cs); args->jump_functions = XCNEWVEC (struct ipa_jump_func,
call_tree = get_call_expr_in (ipa_callsite_tree (cs)); ipa_get_cs_argument_count (args));
call_tree = get_call_expr_in (cs->call_stmt);
gcc_assert (TREE_CODE (call_tree) == CALL_EXPR); gcc_assert (TREE_CODE (call_tree) == CALL_EXPR);
arg_num = 0; arg_num = 0;
FOR_EACH_CALL_EXPR_ARG (arg, iter, call_tree) FOR_EACH_CALL_EXPR_ARG (arg, iter, call_tree)
{ {
/* If the formal parameter was passed as argument, we store /* 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. */ of this argument. */
if ((TREE_CODE (arg) == SSA_NAME if ((TREE_CODE (arg) == SSA_NAME
&& TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL) && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL)
|| TREE_CODE (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); parm_decl = TREE_CODE (arg) == PARM_DECL ? arg : SSA_NAME_VAR (arg);
i = ipa_method_tree_map (mt, parm_decl); index = ipa_get_param_decl_index (info, parm_decl);
if (TREE_CODE (arg) == SSA_NAME && IS_VALID_TREE_MAP_INDEX (i)) if (TREE_CODE (arg) == SSA_NAME && IS_VALID_JUMP_FUNC_INDEX (index))
{ {
curr_cfun = DECL_STRUCT_FUNCTION (mt->decl); curr_cfun = DECL_STRUCT_FUNCTION (mt->decl);
if (!gimple_default_def (curr_cfun, parm_decl) if (!gimple_default_def (curr_cfun, parm_decl)
|| gimple_default_def (curr_cfun, parm_decl) != arg) || 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)) if (!IS_VALID_JUMP_FUNC_INDEX (index) || info->modified_flags[index])
ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE); args->jump_functions[arg_num].type = IPA_UNKNOWN;
else else
{ {
ipa_callsite_param_set_type (cs, arg_num, FORMAL_IPATYPE); args->jump_functions[arg_num].type = IPA_PASS_THROUGH;
ipa_callsite_param_set_info_type_formal (cs, arg_num, i); args->jump_functions[arg_num].value.formal_id = index;
} }
} }
/* If a constant value was passed as argument, /* 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. */ of this argument. */
else if (TREE_CODE (arg) == INTEGER_CST else if (TREE_CODE (arg) == INTEGER_CST
|| TREE_CODE (arg) == REAL_CST || TREE_CODE (arg) == REAL_CST
|| TREE_CODE (arg) == FIXED_CST) || TREE_CODE (arg) == FIXED_CST)
{ {
ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE); args->jump_functions[arg_num].type = IPA_CONST;
ipa_callsite_param_set_info_type (cs, arg_num, arg); args->jump_functions[arg_num].value.constant = arg;
} }
/* This is for the case of Fortran. If the address of a const_decl /* This is for the case of Fortran. If the address of a const_decl
was passed as argument then we store was passed as argument then we store
CONST_IPATYPE_REF/CONST_IPATYPE_REF and the constant IPA_CONST_REF/IPA_CONST_REF and the constant
value as the jump function corresponding to this argument. */ value as the jump function corresponding to this argument. */
else if (TREE_CODE (arg) == ADDR_EXPR else if (TREE_CODE (arg) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (arg, 0)) == CONST_DECL) && TREE_CODE (TREE_OPERAND (arg, 0)) == CONST_DECL)
...@@ -499,121 +306,90 @@ ipa_callsite_compute_param (struct cgraph_edge *cs) ...@@ -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)) == REAL_CST
|| TREE_CODE (DECL_INITIAL (cst_decl)) == FIXED_CST) || TREE_CODE (DECL_INITIAL (cst_decl)) == FIXED_CST)
{ {
ipa_callsite_param_set_type (cs, arg_num, args->jump_functions[arg_num].type = IPA_CONST_REF;
CONST_IPATYPE_REF); args->jump_functions[arg_num].value.constant = cst_decl;
ipa_callsite_param_set_info_type (cs, arg_num,
DECL_INITIAL (cst_decl));
} }
} }
else else
ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE); args->jump_functions[arg_num].type = IPA_UNKNOWN;
arg_num++; arg_num++;
} }
} }
/* Return type of jump function JF. */ /* Allocate and initialize ipa_node_params structure for the given cgraph
enum jump_func_type node. */
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. */
void 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. */ nodes in callgraph. */
void void
ipa_nodes_create (void) ipa_create_all_node_params (void)
{ {
struct cgraph_node *node; struct cgraph_node *node;
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
ipa_node_create (node); ipa_create_node_params (node);
} }
/* Allocate and initialize ipa_edge structure. */ /* Allocate and initialize ipa_edge structure. */
void void
ipa_edges_create (void) ipa_create_all_edge_args (void)
{ {
struct cgraph_node *node; struct cgraph_node *node;
struct cgraph_edge *cs; struct cgraph_edge *cs;
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
for (cs = node->callees; cs; cs = cs->next_callee) for (cs = node->callees; cs; cs = cs->next_callee)
cs->aux = xcalloc (1, sizeof (struct ipa_edge)); cs->aux = xcalloc (1, sizeof (struct ipa_edge_args));
}
/* 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;
}
} }
/* Free ipa_edge structure. */ /* Free ipa_edge structure. */
void void
ipa_edges_free (void) ipa_free_all_edge_args (void)
{ {
struct cgraph_node *node; struct cgraph_node *node;
struct cgraph_edge *cs; struct cgraph_edge *cs;
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
for (cs = node->callees; cs; cs = cs->next_callee) for (cs = node->callees; cs; cs = cs->next_callee)
{ if (cs->aux)
free (cs->aux); {
cs->aux = NULL; 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 void
ipa_free (void) ipa_free_all_node_params (void)
{ {
struct cgraph_node *node; struct cgraph_node *node;
struct cgraph_edge *cs;
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
if (node->aux == NULL) if (node->aux == NULL)
continue; continue;
if (IPA_NODE_REF (node)->ipcp_cval) if (IPA_NODE_REF (node)->ipcp_lattices)
free (IPA_NODE_REF (node)->ipcp_cval); free (IPA_NODE_REF (node)->ipcp_lattices);
if (IPA_NODE_REF (node)->ipa_param_tree) if (IPA_NODE_REF (node)->param_decls)
free (IPA_NODE_REF (node)->ipa_param_tree); free (IPA_NODE_REF (node)->param_decls);
if (IPA_NODE_REF (node)->ipa_mod) if (IPA_NODE_REF (node)->modified_flags)
free (IPA_NODE_REF (node)->ipa_mod); free (IPA_NODE_REF (node)->modified_flags);
for (cs = node->callees; cs; cs = cs->next_callee) free (node->aux);
{ node->aux = NULL;
if (cs->aux)
if (IPA_EDGE_REF (cs)->ipa_param_map)
free (IPA_EDGE_REF (cs)->ipa_param_map);
}
} }
} }
/* 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. */ callgraph to F. */
void void
ipa_method_tree_print (FILE * f) ipa_print_all_tree_maps (FILE * f)
{ {
int i, count; int i, count;
tree temp; tree temp;
...@@ -622,11 +398,12 @@ ipa_method_tree_print (FILE * f) ...@@ -622,11 +398,12 @@ ipa_method_tree_print (FILE * f)
fprintf (f, "\nPARAM TREE MAP PRINT\n"); fprintf (f, "\nPARAM TREE MAP PRINT\n");
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
fprintf (f, "method %s Trees :: \n", cgraph_node_name (node)); struct ipa_node_params *info = IPA_NODE_REF (node);
count = ipa_method_formal_count (node); fprintf (f, "function %s Trees :: \n", cgraph_node_name (node));
count = ipa_get_param_count (info);
for (i = 0; i < count; i++) 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) if (TREE_CODE (temp) == PARM_DECL)
fprintf (f, " param [%d] : %s\n", i, fprintf (f, " param [%d] : %s\n", i,
(*lang_hooks.decl_printable_name) (temp, 2)); (*lang_hooks.decl_printable_name) (temp, 2));
...@@ -635,10 +412,10 @@ ipa_method_tree_print (FILE * f) ...@@ -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. */ callgraph to F. */
void void
ipa_method_modify_print (FILE * f) ipa_print_all_params_modified (FILE * f)
{ {
int i, count; int i, count;
bool temp; bool temp;
...@@ -647,11 +424,12 @@ ipa_method_modify_print (FILE * f) ...@@ -647,11 +424,12 @@ ipa_method_modify_print (FILE * f)
fprintf (f, "\nMODIFY PRINT\n"); fprintf (f, "\nMODIFY PRINT\n");
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
fprintf (f, "method %s :: \n", cgraph_node_name (node)); struct ipa_node_params *info = IPA_NODE_REF (node);
count = ipa_method_formal_count (node); fprintf (f, "function %s :: \n", cgraph_node_name (node));
count = ipa_get_param_count (info);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
temp = ipa_method_is_modified (node, i); temp = info->modified_flags[i];
if (temp) if (temp)
fprintf (f, " param [%d] true \n", i); fprintf (f, " param [%d] true \n", i);
else else
...@@ -659,3 +437,4 @@ ipa_method_modify_print (FILE * f) ...@@ -659,3 +437,4 @@ ipa_method_modify_print (FILE * f)
} }
} }
} }
...@@ -30,43 +30,42 @@ along with GCC; see the file COPYING3. If not see ...@@ -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. Formal - the caller's formal parameter is passed as an actual argument.
Constant - a constant is passed as an actual argument. Constant - a constant is passed as an actual argument.
Unknown - neither of the above. Unknown - neither of the above.
Integer and real constants are represented as CONST_IPATYPE and Fortran Integer and real constants are represented as IPA_CONST and Fortran
constants are represented as CONST_IPATYPE_REF. */ constants are represented as IPA_CONST_REF. */
enum jump_func_type enum jump_func_type
{ {
UNKNOWN_IPATYPE, IPA_UNKNOWN,
CONST_IPATYPE, IPA_CONST,
CONST_IPATYPE_REF, IPA_CONST_REF,
FORMAL_IPATYPE IPA_PASS_THROUGH
}; };
/* All formal parameters in the program have a cval computed by /* All formal parameters in the program have a lattice associated with it
the interprocedural stage of IPCP. computed by the interprocedural stage of IPCP.
There are three main values of cval : There are three main values of the lattice:
TOP - unknown. TOP - unknown.
BOTTOM - non constant. BOTTOM - non constant.
CONSTANT_TYPE - constant value. CONSTANT_TYPE - constant value.
Cval of formal f will have a constant value if all callsites to this Cval of formal f will have a constant value if all callsites to this
function have the same constant value passed to f. function have the same constant value passed to f.
Integer and real constants are represented as CONST_IPATYPE and Fortran Integer and real constants are represented as IPA_CONST and Fortran
constants are represented as CONST_IPATYPE_REF. */ constants are represented as IPA_CONST_REF. */
enum cvalue_type enum ipa_lattice_type
{ {
BOTTOM, IPA_BOTTOM,
CONST_VALUE, IPA_CONST_VALUE,
CONST_VALUE_REF, IPA_CONST_VALUE_REF,
TOP IPA_TOP
}; };
/* Represents the value of either jump function or cval. /* Represents a value of a jump function.
value represents a constant. value represents a constant.
formal_id is used only in jump function context and represents formal_id is used only in jump function context and represents
pass-through parameter (the formal of caller is passed pass-through parameter (the formal of caller is passed as argument). */
as argument). */ union jump_func_value
union parameter_info
{ {
unsigned int formal_id; unsigned int formal_id;
tree value; tree constant;
}; };
/* A jump function for a callsite represents the values passed as actual /* A jump function for a callsite represents the values passed as actual
...@@ -75,16 +74,16 @@ union parameter_info ...@@ -75,16 +74,16 @@ union parameter_info
struct ipa_jump_func struct ipa_jump_func
{ {
enum jump_func_type type; 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 /* All formal parameters in the program have a cval computed by
the interprocedural stage of IPCP. See enum cvalue_type for the interprocedural stage of IPCP. See enum ipa_lattice_type for
the various types of cvals supported */ the various types of lattices supported */
struct ipcp_formal struct ipcp_lattice
{ {
enum cvalue_type cval_type; enum ipa_lattice_type type;
union parameter_info cvalue; tree constant;
}; };
/* Represent which DECL tree (or reference to such tree) /* Represent which DECL tree (or reference to such tree)
...@@ -102,103 +101,165 @@ struct ipa_replace_map ...@@ -102,103 +101,165 @@ struct ipa_replace_map
}; };
/* Return the field in cgraph_node/cgraph_edge struct that points /* Return the field in cgraph_node/cgraph_edge struct that points
to ipa_node/ipa_edge struct. */ to ipa_node_params/ipa_edge_args struct. */
#define IPA_NODE_REF(MT) ((struct ipa_node *)(MT)->aux) #define IPA_NODE_REF(MT) ((struct ipa_node_params *)(MT)->aux)
#define IPA_EDGE_REF(EDGE) ((struct ipa_edge *)(EDGE)->aux) #define IPA_EDGE_REF(EDGE) ((struct ipa_edge_args *)(EDGE)->aux)
/* This macro checks validity of index returned by /* This macro checks validity of index returned by
ipa_method_tree_map function. */ ipa_get_param_decl_index function. */
#define IS_VALID_TREE_MAP_INDEX(I) ((I) != -1) #define IS_VALID_JUMP_FUNC_INDEX(I) ((I) != -1)
/* ipa_node stores information related to a method and /* ipa_node_params stores information related to formal parameters of functions
its formal parameters. It is pointed to by a field in the and some other information for interprocedural passes that operate on
method's corresponding cgraph_node. parameters (such as ipa-cp). */
ipa_edge stores information related to a callsite and struct ipa_node_params
its arguments. It is pointed to by a field in the
callsite's corresponding cgraph_edge. */
struct ipa_node
{ {
/* Number of formal parameters of this method. When set to 0, /* Number of formal parameters of this function. When set to 0,
this method's parameters would not be analyzed by the different this functions's parameters would not be analyzed by the different
stages of IPA CP. */ stages of IPA CP. */
int ipa_arg_num; int param_count;
/* Array of cvals. */ /* Array of lattices. */
struct ipcp_formal *ipcp_cval; struct ipcp_lattice *ipcp_lattices;
/* Mapping each parameter to its PARM_DECL tree. */ /* Mapping each parameter to its PARM_DECL tree. */
tree *ipa_param_tree; tree *param_decls;
/* Indicating which parameter is modified in its method. */ /* Indicating which parameter is modified in its function. */
bool *ipa_mod; bool *modified_flags;
/* Only for versioned nodes this field would not be NULL, /* Only for versioned nodes this field would not be NULL,
it points to the node that IPA cp cloned from. */ it points to the node that IPA cp cloned from. */
struct cgraph_node *ipcp_orig_node; 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 ratio between the direct calls and sum of all invocations of
this function (given by profiling info). It is used to calculate this function (given by profiling info). It is used to calculate
the profiling information of the original function and the versioned the profiling information of the original function and the versioned
one. */ one. */
gcov_type count_scale; 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, /* Number of actual arguments in this callsite. When set to 0,
this callsite's parameters would not be analyzed by the different this callsite's parameters would not be analyzed by the different
stages of IPA CP. */ stages of IPA CP. */
int ipa_param_num; int argument_count;
/* Array of the callsite's jump function of each parameter. */ /* 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 /* ipa_edge_args access functions. Please use these to access fields that
to create a temporary worklist used in are or will be shared among various passes. */
the propagation stage of IPCP. (can be used for more IPA
optimizations) */ /* Set the number of actual arguments. */
struct ipa_methodlist static inline void
ipa_set_cs_argument_count (struct ipa_edge_args *args, int count)
{ {
struct cgraph_node *method_p; args->argument_count = count;
struct ipa_methodlist *next_method; }
/* 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. */ /* ipa_func_list interface. */
typedef struct ipa_methodlist *ipa_methodlist_p; struct ipa_func_list *ipa_init_func_list (void);
void ipa_push_func_to_list (struct ipa_func_list **, struct cgraph_node *);
/* ipa_methodlist interface. */ struct cgraph_node *ipa_pop_func_from_list (struct ipa_func_list **);
ipa_methodlist_p ipa_methodlist_init (void);
bool ipa_methodlist_not_empty (ipa_methodlist_p); /* Callsite related calculations. */
void ipa_add_method (ipa_methodlist_p *, struct cgraph_node *); void ipa_compute_jump_functions (struct cgraph_edge *);
struct cgraph_node *ipa_remove_method (ipa_methodlist_p *); void ipa_count_arguments (struct cgraph_edge *);
/* ipa_callsite interface. */ /* Function parameters related computations. */
int ipa_callsite_param_count (struct cgraph_edge *); void ipa_count_formal_params (struct cgraph_node *);
void ipa_callsite_param_count_set (struct cgraph_edge *, int); void ipa_create_param_decls_array (struct cgraph_node *);
struct ipa_jump_func *ipa_callsite_param (struct cgraph_edge *, int); void ipa_detect_param_modifications (struct cgraph_node *);
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);
/* 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. */ /* Debugging interface. */
void ipa_method_tree_print (FILE *); void ipa_print_all_tree_maps (FILE *);
void ipa_method_modify_print (FILE *); void ipa_print_all_params_modified (FILE *);
#endif /* IPA_PROP_H */ #endif /* IPA_PROP_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment