cvs diff: Diffing . Index: common.opt =================================================================== RCS file: /cvs/gcc/gcc/gcc/common.opt,v retrieving revision 1.14.2.20.2.25 diff -c -3 -p -r1.14.2.20.2.25 common.opt *** common.opt 15 Apr 2005 13:25:43 -0000 1.14.2.20.2.25 --- common.opt 29 Apr 2005 15:21:21 -0000 *************** fipa-cp *** 924,929 **** --- 924,933 ---- Common Report Var(flag_ipa_cp) Perform IPA constant propagation + fipa-alias + Common Report Var(flag_ipa_alias) + Perform IPA alias analysis + funroll-loops Common Report Var(flag_unroll_loops) Perform loop unrolling when iteration count is known Index: ipa_prop.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/Attic/ipa_prop.c,v retrieving revision 1.1.2.5 diff -c -3 -p -r1.1.2.5 ipa_prop.c *** ipa_prop.c 21 Mar 2005 09:08:52 -0000 1.1.2.5 --- ipa_prop.c 29 Apr 2005 15:21:21 -0000 *************** of the callsite. There are three types o *** 68,76 **** In order to compute the jump functions, we need the modify information for the formal parameters of methods. ! The jump function info, ipcp_jump_func, is defined in ipa_edge structure (defined in ipa_prop.h and pointed to by cgraph_node->aux) ! The modify info, ipcp_modify, is defined in ipa_node structure (defined in ipa_prop.h and pointed to by cgraph_edge->aux). -ipcp_init_stage() is the first stage driver. --- 68,76 ---- In order to compute the jump functions, we need the modify information for the formal parameters of methods. ! 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 (defined in ipa_prop.h and pointed to by cgraph_edge->aux). -ipcp_init_stage() is the first stage driver. *************** Then the callsites are traversed and upd *** 123,128 **** --- 123,154 ---- */ + /* The interprocedural aliasing analysis is analysis of formals + based on the following article: + + Keith D. Cooper and Ken Kennedy, "Fast interprocedural alias analysis", + 16th ACM Symposium on Principles of Programming Languages. pages 49-57., + Jan 11-13 1989, Austin, Texas. + + The analysis comprises three stages: (1) initialization, (2) propagation + and (3) stage of preserving results of ipaa analysis for subsequent + compilation stages (this stage is not implemented yet). + + (1) this stage is done by ipa_init_stage () function when called with + IPA_ALIAS_ANALYSIS value. Intraprocedural analysis are used to define + aliasing of actual parameters at callsites. For now, only combinations + of local arrays and formals are considered. Formals and local arrays + which were modified inside the function, or which have their addresses + taken, are removed from consideration. + + (2) this stage is done in ipaa_propagate_stage (); starting from callers + the aliasing info which was calculated at the initialization stage is + propagated to callees and further on to callers of callees. + + The flag "-fipa-alias" activate this optimization. + + */ + #include "config.h" #include "system.h" #include "coretypes.h" *************** Then the callsites are traversed and upd *** 141,227 **** #include "flags.h" #include "timevar.h" ! typedef struct cgraph_node *ipcp_method ; ! typedef struct cgraph_edge *ipcp_callsite; ! struct ipcp_methodlist GTY(()) { ! ipcp_method method_p; ! struct ipcp_methodlist *next_method; }; ! typedef struct ipcp_methodlist *ipcp_methodlist_p; ! /* ipcp_worlList Interface. */ ! static inline ipcp_methodlist_p ipcp_create_methodlist_node (void); ! static inline bool ipcp_methodlist_not_empty (ipcp_methodlist_p); ! static inline ipcp_method ipcp_methodlist_method (ipcp_methodlist_p); ! static inline void ipcp_methodlist_method_set (ipcp_methodlist_p, ipcp_method); ! static inline ipcp_methodlist_p ipcp_methodlist_next_method (ipcp_methodlist_p); ! static inline void ipcp_methodlist_next_method_set (ipcp_methodlist_p, ! ipcp_methodlist_p); ! static void ipcp_add_method (ipcp_methodlist_p *, ipcp_method); ! static ipcp_method ipcp_remove_method (ipcp_methodlist_p *); ! static ipcp_methodlist_p ipcp_methodlist_init (void); ! ! /* ipcp_callsite interface. */ ! static inline int ipcp_callsite_param_count (ipcp_callsite); ! static inline void ipcp_callsite_param_count_set (ipcp_callsite, int); ! static inline struct ipcp_jump_func *ipcp_callsite_param (ipcp_callsite, int); ! static inline ipcp_method ipcp_callsite_callee (ipcp_callsite); ! static inline void ipcp_callsite_param_set_type (ipcp_callsite, int, enum Jfunc_type); ! static inline void ipcp_callsite_param_set_info_type_formal (ipcp_callsite cs, int i, unsigned int formal) ; ! static inline void ipcp_callsite_param_set_info_type_int (ipcp_callsite cs, int i, ipcp_int *info_type1) ; ! static inline void ipcp_callsite_param_map_create (ipcp_callsite); ! static inline tree ipcp_callsite_tree (ipcp_callsite); ! static inline ipcp_method ipcp_callsite_caller (ipcp_callsite); ! static void ipcp_callsite_compute_param (ipcp_callsite); ! static void ipcp_callsite_compute_count (ipcp_callsite); /* ipcp_method interface. */ ! static inline void ipa_node_create (ipcp_method); ! static inline bool ipcp_method_is_cloned (ipcp_method); ! static inline void ipcp_method_set_orig_node (ipcp_method, ipcp_method); ! static inline ipcp_method ipcp_method_orig_node (ipcp_method); ! static inline void ipcp_formal_create (ipcp_method); ! static inline int ipcp_method_formal_count (ipcp_method); ! static inline void ipcp_method_formal_count_set (ipcp_method, int); ! static inline void ipcp_method_cval_set (ipcp_method, int, struct ipcp_formal*); ! static inline struct ipcp_formal *ipcp_method_cval (ipcp_method, int); ! static inline void ipcp_method_cval_set_cvalue_type (ipcp_method, int, enum Cvalue_type); - static inline bool ipcp_method_is_modified (ipcp_method, int); - static inline tree ipcp_method_get_tree (ipcp_method, int); - static inline void ipcp_method_tree_map_create (ipcp_method); - static inline void ipcp_method_modify_create (ipcp_method); - static inline void ipcp_method_modify_set (ipcp_method, int, bool); - static void ipa_cloned_create (ipcp_method orig_node, ipcp_method new_node); - static int ipcp_method_tree_map (ipcp_method, tree); - static void ipcp_method_compute_tree_map (ipcp_method); static void ipcp_cval_meet (struct ipcp_formal *, struct ipcp_formal *, struct ipcp_formal *); ! static void ipcp_cval_compute (struct ipcp_formal *, ipcp_method, enum Jfunc_type, union info *); static bool ipcp_cval_changed (struct ipcp_formal *, struct ipcp_formal *); static bool ipcp_type_is_const (enum Cvalue_type); ! static void ipcp_method_formal_compute_count (ipcp_method); ! static void ipcp_method_cval_init (ipcp_method); ! static tree ipcp_modify_walk_tree (tree *, int *, void *); ! static void ipcp_modify_walk_tree_1 (tree *, void *); ! static void ipcp_method_modify_init (ipcp_method); ! static void ipcp_method_compute_modify (ipcp_method); /* jump function interface. */ ! static inline enum Jfunc_type get_type (struct ipcp_jump_func *); ! static inline union info *ipcp_jf_get_info_type (struct ipcp_jump_func *); ! static inline void ipcp_int2ipcp_int (ipcp_int *, int); static inline int ipcp_get_int (ipcp_int *); /* cval interface. */ static inline void ipcp_cval_set_cvalue_type (struct ipcp_formal *, enum Cvalue_type); --- 167,261 ---- #include "flags.h" #include "timevar.h" ! typedef struct cgraph_node *ipa_method ; ! typedef struct cgraph_edge *ipa_callsite; ! struct ipa_methodlist GTY(()) { ! ipa_method method_p; ! struct ipa_methodlist *next_method; }; ! typedef struct ipa_methodlist *ipa_methodlist_p; ! /* ipa_worlList Interface. */ ! static inline ipa_methodlist_p ipa_create_methodlist_node (void); ! static inline bool ipa_methodlist_not_empty (ipa_methodlist_p); ! static inline ipa_method ipa_methodlist_method (ipa_methodlist_p); ! static inline void ipa_methodlist_method_set (ipa_methodlist_p, ipa_method); ! static inline ipa_methodlist_p ipa_methodlist_next_method (ipa_methodlist_p); ! static inline void ipa_methodlist_next_method_set (ipa_methodlist_p, ! ipa_methodlist_p); ! static void ipa_add_method (ipa_methodlist_p *, ipa_method); ! static ipa_method ipa_remove_method (ipa_methodlist_p *); ! static ipa_methodlist_p ipa_methodlist_init (void); ! ! /* ipa_callsite interface. */ ! static inline int ipa_callsite_param_count (ipa_callsite); ! static inline void ipa_callsite_param_count_set (ipa_callsite, int); ! static inline struct ipa_jump_func *ipa_callsite_param (ipa_callsite, int); ! static inline ipa_method ipa_callsite_callee (ipa_callsite); ! static inline void ipa_callsite_param_set_type (ipa_callsite, int, enum Jfunc_type); ! static inline void ipa_callsite_param_set_info_type_formal (ipa_callsite cs, int i, unsigned int formal) ; ! static inline void ipa_callsite_param_set_info_type_int (ipa_callsite cs, int i, ipcp_int *info_type1) ; ! static inline void ipa_callsite_param_map_create (ipa_callsite); ! static inline tree ipa_callsite_tree (ipa_callsite); ! static inline ipa_method ipa_callsite_caller (ipa_callsite); ! static void ipa_callsite_compute_param (ipa_callsite); ! static void ipa_callsite_compute_count (ipa_callsite); ! ! /* ipa_method interface. */ ! static inline void ipa_node_create (ipa_method); ! static inline ipa_method ipcp_method_orig_node (ipa_method); ! static inline int ipa_method_formal_count (ipa_method); ! static inline void ipa_method_formal_count_set (ipa_method, int); ! static inline bool ipa_method_is_modified (ipa_method, int); ! static inline tree ipa_method_get_tree (ipa_method, int); ! static inline void ipa_method_tree_map_create (ipa_method); ! static inline void ipa_method_modify_create (ipa_method); ! static inline void ipa_method_modify_set (ipa_method, int, bool); ! static void ipa_cloned_create (ipa_method orig_node, ipa_method new_node); ! static int ipa_method_tree_map (ipa_method, tree); ! static void ipa_method_compute_tree_map (ipa_method); ! static void ipa_method_formal_compute_count (ipa_method); ! static tree ipa_modify_walk_tree (tree *, int *, void *); ! static void ipa_modify_walk_tree_1 (tree *, void *); ! static void ipa_method_modify_init (ipa_method); ! static void ipa_method_compute_modify (ipa_method); /* ipcp_method interface. */ ! static inline bool ipcp_method_is_cloned (ipa_method); ! static inline void ipcp_method_set_orig_node (ipa_method, ipa_method); ! static inline void ipcp_formal_create (ipa_method); ! static inline void ipcp_method_cval_set (ipa_method, int, struct ipcp_formal*); ! static inline struct ipcp_formal *ipcp_method_cval (ipa_method, int); ! static inline void ipcp_method_cval_set_cvalue_type (ipa_method, int, enum Cvalue_type); static void ipcp_cval_meet (struct ipcp_formal *, struct ipcp_formal *, struct ipcp_formal *); ! static void ipcp_cval_compute (struct ipcp_formal *, ipa_method, enum Jfunc_type, union info *); static bool ipcp_cval_changed (struct ipcp_formal *, struct ipcp_formal *); static bool ipcp_type_is_const (enum Cvalue_type); ! static void ipcp_method_cval_init (ipa_method); /* jump function interface. */ ! static inline enum Jfunc_type get_type (struct ipa_jump_func *); ! static inline union info *ipa_jf_get_info_type (struct ipa_jump_func *); static inline void ipcp_int2ipcp_int (ipcp_int *, int); static inline int ipcp_get_int (ipcp_int *); + /* ipa high level interface. */ + static void ipa_driver (enum ipa_analysis_type); + static void ipa_init_stage (enum ipa_analysis_type); + static void ipa_free (void); + static void ipa_nodes_create (void); + static void ipa_edges_create (void); + /* cval interface. */ static inline void ipcp_cval_set_cvalue_type (struct ipcp_formal *, enum Cvalue_type); *************** static inline enum Cvalue_type ipcp_cval *** 231,460 **** static inline bool ipcp_cval_equal_cvalues (union info *const_val1, union info *const_val2, enum Cvalue_type type1, enum Cvalue_type type2); - static void ipcp_init_stage (void); static void ipcp_iterate_stage (void); static bool ipcp_after_propagate (void); static void ipcp_propagate_stage (void); static void ipcp_insert_stage (void); static void ipcp_update_callgraph (void); ! static bool ipcp_redirect (ipcp_callsite); ! static void ipcp_free (void); ! static void ipa_nodes_create (void); ! static void ipa_edges_create (void); ! static bool ipcp_method_dont_insert_const (ipcp_method); static tree ipcp_asm_walk_tree (tree *, int *, void *); static tree ipcp_asm_walk_tree_1 (tree *); ! static bool ipcp_method_contains_asm (ipcp_method); ! static void ipcp_propagate_const (ipcp_method, int, union info *, enum Cvalue_type); static void constant_val_insert (tree, tree, tree); ! /* Debugging interface. */ static void ipcp_structures_print (FILE *); static void ipcp_method_cval_print (FILE *); ! static void ipcp_method_tree_print (FILE *); ! static void ipcp_method_modify_print (FILE *); ! static void ipcp_callsite_param_print (FILE *f); /* WorlList Interface. */ /* Creates the worklist for ipcp_iterate_stage(). */ ! static inline ipcp_methodlist_p ! ipcp_create_methodlist_node (void) { ! return ggc_alloc (sizeof (struct ipcp_methodlist)); } /* Checks that worklist is not empty. */ static inline bool ! ipcp_methodlist_not_empty (ipcp_methodlist_p wl) { return (wl != NULL); } /* Gets method from worklist's node. */ ! static inline ipcp_method ! ipcp_methodlist_method (ipcp_methodlist_p wl) { return wl->method_p; } /* Sets worklist's node to point to mt. */ static inline void ! ipcp_methodlist_method_set (ipcp_methodlist_p wl, ipcp_method mt) { wl->method_p = mt; } /* Gets next worklist's node. */ ! static inline ipcp_methodlist_p ! ipcp_methodlist_next_method (ipcp_methodlist_p wl) { return wl->next_method; } /* Sets worklist node wl1 to point to worklist node wl2. */ static inline void ! ipcp_methodlist_next_method_set (ipcp_methodlist_p wl1, ipcp_methodlist_p wl2) { wl1->next_method = wl2; } /* Initializing a worklist to contain all methods. */ ! static ipcp_methodlist_p ! ipcp_methodlist_init(void) { ! ipcp_method node; ! ipcp_methodlist_p wl; wl = NULL; for (node = cgraph_nodes; node; node = node->next) ! ipcp_add_method (&wl, node); return wl; } /* Adding a method to the worklist. */ static void ! ipcp_add_method (ipcp_methodlist_p *wl, ipcp_method mt) { ! ipcp_methodlist_p temp; ! temp = ipcp_create_methodlist_node (); ! ipcp_methodlist_method_set (temp, mt); ! ipcp_methodlist_next_method_set (temp, *wl); *wl = temp; } /* Removing a method from the worklist. */ ! static ipcp_method ! ipcp_remove_method (ipcp_methodlist_p *wl) { ! ipcp_methodlist_p first; first = *wl; ! *wl = ipcp_methodlist_next_method (*wl); ! return ipcp_methodlist_method (first); } ! /* ipcp_callsite interface. */ /* Gets how many arguments the callsite has. */ static inline int ! ipcp_callsite_param_count (ipcp_callsite cs) { ! return ((struct ipa_edge *)cs->aux)->ipcp_param_num; } /* Sets how many arguments the callsite has. */ static inline void ! ipcp_callsite_param_count_set (ipcp_callsite cs, int i) { ! ((struct ipa_edge *)cs->aux)->ipcp_param_num = i; } /* Gets the jump function for argument i of callsite cs. */ ! static inline struct ipcp_jump_func * ! ipcp_callsite_param (ipcp_callsite cs, int i) { ! return &(((struct ipa_edge *)cs->aux)->ipcp_param_map[i]); } /* Gets the callee of callsite cs. */ ! static inline ipcp_method ! ipcp_callsite_callee (ipcp_callsite cs) { return cs->callee; } /* Sets the jump function's type for argument i of callsite cs. */ static inline void ! ipcp_callsite_param_set_type (ipcp_callsite cs, int i, enum Jfunc_type type1) { ! ((struct ipa_edge *)cs->aux)->ipcp_param_map[i].type = type1; } /* Sets formal to the callsite's info type (for argument i). */ static inline void ! ipcp_callsite_param_set_info_type_formal (ipcp_callsite cs, int i, unsigned int formal) { ! ipcp_callsite_param (cs, i)->info_type.formal_id = formal; } /* Sets int value to the callsite's info type (for argument i). */ static inline void ! ipcp_callsite_param_set_info_type_int (ipcp_callsite cs, int i, ipcp_int *info_type1) { ! ipcp_callsite_param (cs, i)->info_type.int_value.high = info_type1->high; ! ipcp_callsite_param (cs, i)->info_type.int_value.low = info_type1->low; } /* Sets float value to the callsite's info type (for argument i). */ static inline void ! ipcp_callsite_param_set_info_type_float (ipcp_callsite cs, int i, REAL_VALUE_TYPE *info_type1) { ! ipcp_callsite_param (cs, i)->info_type.float_value = *info_type1; } /* Allocates space for the jump functions. */ static inline void ! ipcp_callsite_param_map_create (ipcp_callsite cs) { ! ((struct ipa_edge *)cs->aux)->ipcp_param_map = ! xcalloc (ipcp_callsite_param_count (cs), sizeof (struct ipcp_jump_func)); } /* Returns the call expr tree realted to callsite cs. */ static inline tree ! ipcp_callsite_tree (ipcp_callsite cs) { return cs->call_expr; } /* Gets the caller of callsite cs. */ ! static inline ipcp_method ! ipcp_callsite_caller (ipcp_callsite cs) { return cs->caller; } /* Counts how many arguments this callsite has. */ static void ! ipcp_callsite_compute_count (ipcp_callsite cs) { tree callTree; tree arg; int arg_num; ! callTree = ipcp_callsite_tree (cs); if (TREE_CODE(callTree) != CALL_EXPR) abort(); arg = TREE_OPERAND (callTree, 1); arg_num=0; for (; arg != NULL_TREE; arg = TREE_CHAIN (arg)) arg_num++; ! ipcp_callsite_param_count_set (cs,arg_num); } /* Computes jump functions and inserts the information ! in the ipcp_param_map array. */ static void ! ipcp_callsite_compute_param (ipcp_callsite cs) { tree callTree; tree arg, cst_decl; int arg_num; int i; ! ipcp_method mt; ! if (ipcp_callsite_param_count(cs) == 0) return; ! ipcp_callsite_param_map_create (cs); ! callTree = ipcp_callsite_tree (cs); if (TREE_CODE(callTree) != CALL_EXPR) abort(); arg = TREE_OPERAND (callTree, 1); --- 265,581 ---- static inline bool ipcp_cval_equal_cvalues (union info *const_val1, union info *const_val2, enum Cvalue_type type1, enum Cvalue_type type2); static void ipcp_iterate_stage (void); static bool ipcp_after_propagate (void); static void ipcp_propagate_stage (void); static void ipcp_insert_stage (void); static void ipcp_update_callgraph (void); ! static bool ipcp_redirect (ipa_callsite); ! static bool ipcp_method_dont_insert_const (ipa_method); static tree ipcp_asm_walk_tree (tree *, int *, void *); static tree ipcp_asm_walk_tree_1 (tree *); ! static bool ipcp_method_contains_asm (ipa_method); ! static void ipcp_propagate_const (ipa_method, int, union info *, enum Cvalue_type); static void constant_val_insert (tree, tree, tree); ! /* ipa common debugging interface. */ ! static void ipa_method_tree_print (FILE *); ! static void ipa_method_modify_print (FILE *); ! ! /* ipcp debugging interface. */ static void ipcp_structures_print (FILE *); static void ipcp_method_cval_print (FILE *); ! static void ipcp_callsite_param_print (FILE *); ! ! /* ipaa debug interface. */ ! static void ipaa_structures_print (FILE *); ! static void ipaa_callsite_param_trees_print (FILE *); ! static void ipaa_callsite_addr_local_array_print (FILE *, tree); ! static void ipaa_method_alias_info_print (FILE *); ! static void ipaa_callsite_alias_info_print (FILE *); ! ! /* ipaa_method interface */ ! static inline void ipaa_method_create_alias_info (ipa_method); ! static inline void ipaa_method_alias_init (ipa_method); ! static inline void ipaa_method_set_num_pairs_args (ipa_method, int); ! static inline int ipaa_method_get_num_pairs_args (ipa_method); ! static inline void ipaa_method_compute_num_pairs (ipa_method); ! static inline void ipaa_method_set_pair_alias_info (ipa_method, ipaa_alias_info, ! int /* first index */, ! int /* second index */); ! static inline ipaa_alias_info ipaa_method_get_pair_alias_info (ipa_method, ! int /* first index */, ! int /* second index */); ! static inline void ipaa_method_set_alias_info (ipa_method, ipaa_alias_info, int); ! static inline ipaa_alias_info ipaa_method_get_alias_info (ipa_method, int); ! ! /* ipaa_callsite interface */ ! static inline void ipaa_callsite_create_alias_info (ipa_callsite); ! static inline void ipaa_callsite_alias_init (ipa_callsite); ! static inline void ipaa_callsite_compute_num_pairs (ipa_callsite); ! static inline void ipaa_callsite_set_num_pairs_args (ipa_callsite, int); ! static inline int ipaa_callsite_get_num_pairs_args (ipa_callsite); ! static inline void ipaa_callsite_compute_param (ipa_callsite); ! static inline void ipaa_callsite_set_pair_alias_info (ipa_callsite, ipaa_alias_info, ! int /* first index */, ! int /* second index */); ! static inline ipaa_alias_info ipaa_callsite_get_pair_alias_info (ipa_callsite, ! int /* first index */, ! int /* second index */); ! static inline void ipaa_callsite_set_alias_info (ipa_callsite, ipaa_alias_info, int); ! static inline ipaa_alias_info ipaa_callsite_get_alias_info (ipa_callsite, int); ! ! struct ipaa_varslist GTY(()) ! { ! bool modified; ! tree var_decl; ! tree call_expr; ! struct ipaa_varslist *next_var; ! }; ! ! typedef struct ipaa_varslist *ipaa_varslist_p; ! ! /* ipaa_varslist Interface. */ ! static inline ipaa_varslist_p ipaa_create_varslist_node (void); ! static inline bool ipaa_varslist_not_empty (ipaa_varslist_p); ! static inline tree ipaa_varslist_var (ipaa_varslist_p); ! static inline void ipaa_varslist_var_set (ipaa_varslist_p, tree); ! static inline bool ipaa_varslist_modified (ipaa_varslist_p); ! static inline void ipaa_varslist_modified_set (ipaa_varslist_p, bool); ! static inline ipaa_varslist_p ipaa_varslist_next_var (ipaa_varslist_p); ! static inline void ipaa_varslist_next_var_set (ipaa_varslist_p, ! ipaa_varslist_p); ! static ipaa_varslist_p ipaa_add_var (ipaa_varslist_p, tree, tree); ! static void ipaa_destroy_varslist (ipaa_varslist_p); ! static ipaa_varslist_p ipaa_varslist_init (void); ! static bool ipaa_varslist_is_modified (tree, ipaa_varslist_p); ! static inline tree ipaa_varslist_call_expr (ipaa_varslist_p); ! static inline void ipaa_varslist_call_expr_set (ipaa_varslist_p, tree); ! static void ipaa_print_varslist (FILE *, ipaa_varslist_p); ! ! struct walk_tree_data ! { ! ipaa_varslist_p list; ! tree stmt; ! }; ! ! typedef struct walk_tree_data* walk_tree_data_p; ! ! /* ipaa analysis functions. */ ! static bool ipaa_is_address_of_local_array (tree, tree*, tree); ! static void ipaa_callsites_init_aliasing (ipa_method); ! static ipaa_varslist_p ipaa_varslist_find_var (tree, ipaa_varslist_p); ! static bool ipaa_is_non_modified_formal (ipa_callsite, int, ipa_method); ! static void ipaa_callsites_init_aliasing (ipa_method); ! static void ipaa_method_compute_modify (ipa_method, ipaa_varslist_p); ! static void ipaa_modify_walk_tree_1 (tree *, void *); ! static tree ipaa_modify_walk_tree (tree *t, int *, void *); ! static void ipaa_meet_alias_info (ipaa_alias_info, ipaa_alias_info, ! ipaa_alias_info*); ! static void ipaa_propagate_stage (void); ! static void ipaa_insert_stage (void); ! /* WorlList Interface. */ /* Creates the worklist for ipcp_iterate_stage(). */ ! static inline ipa_methodlist_p ! ipa_create_methodlist_node (void) { ! return ggc_alloc (sizeof (struct ipa_methodlist)); } /* Checks that worklist is not empty. */ static inline bool ! ipa_methodlist_not_empty (ipa_methodlist_p wl) { return (wl != NULL); } /* Gets method from worklist's node. */ ! static inline ipa_method ! ipa_methodlist_method (ipa_methodlist_p wl) { return wl->method_p; } /* Sets worklist's node to point to mt. */ static inline void ! ipa_methodlist_method_set (ipa_methodlist_p wl, ipa_method mt) { wl->method_p = mt; } /* Gets next worklist's node. */ ! static inline ipa_methodlist_p ! ipa_methodlist_next_method (ipa_methodlist_p wl) { return wl->next_method; } /* Sets worklist node wl1 to point to worklist node wl2. */ static inline void ! ipa_methodlist_next_method_set (ipa_methodlist_p wl1, ipa_methodlist_p wl2) { wl1->next_method = wl2; } /* Initializing a worklist to contain all methods. */ ! static ipa_methodlist_p ! ipa_methodlist_init(void) { ! ipa_method node; ! ipa_methodlist_p wl; wl = NULL; for (node = cgraph_nodes; node; node = node->next) ! ipa_add_method (&wl, node); return wl; } /* Adding a method to the worklist. */ static void ! ipa_add_method (ipa_methodlist_p *wl, ipa_method mt) { ! ipa_methodlist_p temp; ! temp = ipa_create_methodlist_node (); ! ipa_methodlist_method_set (temp, mt); ! ipa_methodlist_next_method_set (temp, *wl); *wl = temp; } /* Removing a method from the worklist. */ ! static ipa_method ! ipa_remove_method (ipa_methodlist_p *wl) { ! ipa_methodlist_p first; first = *wl; ! *wl = ipa_methodlist_next_method (*wl); ! return ipa_methodlist_method (first); } ! /* ipa_callsite interface. */ /* Gets how many arguments the callsite has. */ static inline int ! ipa_callsite_param_count (ipa_callsite cs) { ! return ((struct ipa_edge *)cs->aux)->ipa_param_num; } /* Sets how many arguments the callsite has. */ static inline void ! ipa_callsite_param_count_set (ipa_callsite cs, int i) { ! ((struct ipa_edge *)cs->aux)->ipa_param_num = i; } /* Gets the jump function for argument i of callsite cs. */ ! static inline struct ipa_jump_func * ! ipa_callsite_param (ipa_callsite cs, int i) { ! return &(((struct ipa_edge *)cs->aux)->ipa_param_map[i]); } /* Gets the callee of callsite cs. */ ! static inline ipa_method ! ipa_callsite_callee (ipa_callsite cs) { return cs->callee; } /* Sets the jump function's type for argument i of callsite cs. */ static inline void ! ipa_callsite_param_set_type (ipa_callsite cs, int i, enum Jfunc_type type1) { ! ((struct ipa_edge *)cs->aux)->ipa_param_map[i].type = type1; } /* Sets formal to the callsite's info type (for argument i). */ static inline void ! ipa_callsite_param_set_info_type_formal (ipa_callsite cs, int i, unsigned int formal) { ! ipa_callsite_param (cs, i)->info_type.formal_id = formal; } /* Sets int value to the callsite's info type (for argument i). */ static inline void ! ipa_callsite_param_set_info_type_int (ipa_callsite cs, int i, ipcp_int *info_type1) { ! ipa_callsite_param (cs, i)->info_type.int_value.high = info_type1->high; ! ipa_callsite_param (cs, i)->info_type.int_value.low = info_type1->low; } /* Sets float value to the callsite's info type (for argument i). */ static inline void ! ipa_callsite_param_set_info_type_float (ipa_callsite cs, int i, REAL_VALUE_TYPE *info_type1) { ! ipa_callsite_param (cs, i)->info_type.float_value = *info_type1; } /* Allocates space for the jump functions. */ static inline void ! ipa_callsite_param_map_create (ipa_callsite cs) { ! ((struct ipa_edge *)cs->aux)->ipa_param_map = ! xcalloc (ipa_callsite_param_count (cs), sizeof (struct ipa_jump_func)); } /* Returns the call expr tree realted to callsite cs. */ static inline tree ! ipa_callsite_tree (ipa_callsite cs) { return cs->call_expr; } /* Gets the caller of callsite cs. */ ! static inline ipa_method ! ipa_callsite_caller (ipa_callsite cs) { return cs->caller; } /* Counts how many arguments this callsite has. */ static void ! ipa_callsite_compute_count (ipa_callsite cs) { tree callTree; tree arg; int arg_num; ! callTree = ipa_callsite_tree (cs); if (TREE_CODE(callTree) != CALL_EXPR) abort(); arg = TREE_OPERAND (callTree, 1); arg_num=0; for (; arg != NULL_TREE; arg = TREE_CHAIN (arg)) arg_num++; ! ipa_callsite_param_count_set (cs,arg_num); } /* Computes jump functions and inserts the information ! in the ipa_param_map array. */ static void ! ipa_callsite_compute_param (ipa_callsite cs) { tree callTree; tree arg, cst_decl; int arg_num; int i; ! ipa_method mt; ! if (ipa_callsite_param_count(cs) == 0) return; ! ipa_callsite_param_map_create (cs); ! callTree = ipa_callsite_tree (cs); if (TREE_CODE(callTree) != CALL_EXPR) abort(); arg = TREE_OPERAND (callTree, 1); *************** ipcp_callsite_compute_param (ipcp_callsi *** 464,489 **** { if (TREE_CODE (TREE_VALUE (arg)) == PARM_DECL) { ! mt = ipcp_callsite_caller (cs); ! i = ipcp_method_tree_map (mt, TREE_VALUE (arg)); ! if (ipcp_method_is_modified (mt, i)) ! ipcp_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE); else { ! ipcp_callsite_param_set_type (cs, arg_num, FORMAL_IPATYPE); ! ipcp_callsite_param_set_info_type_formal (cs, arg_num, i); } } else if (TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST) { ! ipcp_callsite_param_set_type (cs, arg_num, CONST_IPATYPE_INT); ! ipcp_callsite_param_set_info_type_int (cs, arg_num, &TREE_INT_CST (TREE_VALUE (arg))); } else if (TREE_CODE (TREE_VALUE (arg)) == REAL_CST) { ! ipcp_callsite_param_set_type (cs, arg_num, CONST_IPATYPE_FLOAT); ! ipcp_callsite_param_set_info_type_float (cs, arg_num, TREE_REAL_CST_PTR (TREE_VALUE (arg))); } --- 585,610 ---- { if (TREE_CODE (TREE_VALUE (arg)) == PARM_DECL) { ! mt = ipa_callsite_caller (cs); ! i = ipa_method_tree_map (mt, TREE_VALUE (arg)); ! if (ipa_method_is_modified (mt, i)) ! ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE); else { ! ipa_callsite_param_set_type (cs, arg_num, FORMAL_IPATYPE); ! ipa_callsite_param_set_info_type_formal (cs, arg_num, i); } } else if (TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST) { ! ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE_INT); ! ipa_callsite_param_set_info_type_int (cs, arg_num, &TREE_INT_CST (TREE_VALUE (arg))); } else if (TREE_CODE (TREE_VALUE (arg)) == REAL_CST) { ! ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE_FLOAT); ! ipa_callsite_param_set_info_type_float (cs, arg_num, TREE_REAL_CST_PTR (TREE_VALUE (arg))); } *************** ipcp_callsite_compute_param (ipcp_callsi *** 494,516 **** cst_decl = TREE_OPERAND (TREE_VALUE (arg), 0); if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST) { ! ipcp_callsite_param_set_type (cs, arg_num, CONST_IPATYPE_INT_REF); ! ipcp_callsite_param_set_info_type_int (cs, arg_num, &TREE_INT_CST (DECL_INITIAL (cst_decl))); } else if (TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST) { cst_decl = TREE_OPERAND (TREE_VALUE (arg), 0); ! ipcp_callsite_param_set_type (cs, arg_num, CONST_IPATYPE_FLOAT_REF); ! ipcp_callsite_param_set_info_type_float (cs, arg_num, TREE_REAL_CST_PTR (DECL_INITIAL (cst_decl))); } else ! ipcp_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE); } } else ! ipcp_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE); arg_num++; } } --- 615,637 ---- cst_decl = TREE_OPERAND (TREE_VALUE (arg), 0); if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST) { ! ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE_INT_REF); ! ipa_callsite_param_set_info_type_int (cs, arg_num, &TREE_INT_CST (DECL_INITIAL (cst_decl))); } else if (TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST) { cst_decl = TREE_OPERAND (TREE_VALUE (arg), 0); ! ipa_callsite_param_set_type (cs, arg_num, CONST_IPATYPE_FLOAT_REF); ! ipa_callsite_param_set_info_type_float (cs, arg_num, TREE_REAL_CST_PTR (DECL_INITIAL (cst_decl))); } else ! ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE); } } else ! ipa_callsite_param_set_type (cs, arg_num, UNKNOWN_IPATYPE); arg_num++; } } *************** ipcp_callsite_compute_param (ipcp_callsi *** 520,576 **** /* Allocate and initialize ipa_node structure. */ static inline void ! ipa_node_create (ipcp_method node) { node->aux = xcalloc (1, sizeof (struct ipa_node)); } /* Returns true if node is a cloned/versioned node. */ static inline bool ! ipcp_method_is_cloned (ipcp_method node) { return (ipcp_method_orig_node (node) != NULL); } /* Get orig node of method mt. */ ! static inline ipcp_method ! ipcp_method_orig_node (ipcp_method mt) { return ((struct ipa_node *)mt->aux)->ipcp_orig_node; } /* Sets orig node of method node. */ static inline void ! ipcp_method_set_orig_node (ipcp_method node, ipcp_method orig_node) { ((struct ipa_node *)node->aux)->ipcp_orig_node = orig_node; } /* Create cval structure for method mt. */ static inline void ! ipcp_formal_create (ipcp_method mt) { ((struct ipa_node *)mt->aux)->ipcp_cval = ! xcalloc (ipcp_method_formal_count (mt), sizeof (struct ipcp_formal)); } /* Get number of formals of method mt. */ static inline int ! ipcp_method_formal_count (ipcp_method mt) { ! return ((struct ipa_node *)mt->aux)->ipcp_arg_num; } /* Set number of formals of method mt. */ static inline void ! ipcp_method_formal_count_set (ipcp_method mt, int i) { ! ((struct ipa_node *)mt->aux)->ipcp_arg_num = i; } /* Set cval structure of i-th formal of mt to cval. */ static inline void ! ipcp_method_cval_set (ipcp_method mt, int i, struct ipcp_formal *cval) { ((struct ipa_node *)mt->aux)->ipcp_cval[i].cvalue_type = cval->cvalue_type; ipcp_cval_set_cvalue ( ipcp_method_cval (mt, i), --- 641,697 ---- /* Allocate and initialize ipa_node structure. */ static inline void ! ipa_node_create (ipa_method node) { node->aux = xcalloc (1, sizeof (struct ipa_node)); } /* Returns true if node is a cloned/versioned node. */ static inline bool ! ipcp_method_is_cloned (ipa_method node) { return (ipcp_method_orig_node (node) != NULL); } /* Get orig node of method mt. */ ! static inline ipa_method ! ipcp_method_orig_node (ipa_method mt) { return ((struct ipa_node *)mt->aux)->ipcp_orig_node; } /* Sets orig node of method node. */ static inline void ! ipcp_method_set_orig_node (ipa_method node, ipa_method orig_node) { ((struct ipa_node *)node->aux)->ipcp_orig_node = orig_node; } /* Create cval structure for method mt. */ static inline void ! ipcp_formal_create (ipa_method mt) { ((struct ipa_node *)mt->aux)->ipcp_cval = ! xcalloc (ipa_method_formal_count (mt), sizeof (struct ipcp_formal)); } /* Get number of formals of method mt. */ static inline int ! ipa_method_formal_count (ipa_method mt) { ! return ((struct ipa_node *)mt->aux)->ipa_arg_num; } /* Set number of formals of method mt. */ static inline void ! ipa_method_formal_count_set (ipa_method mt, int i) { ! ((struct ipa_node *)mt->aux)->ipa_arg_num = i; } /* Set cval structure of i-th formal of mt to cval. */ static inline void ! ipcp_method_cval_set (ipa_method mt, int i, struct ipcp_formal *cval) { ((struct ipa_node *)mt->aux)->ipcp_cval[i].cvalue_type = cval->cvalue_type; ipcp_cval_set_cvalue ( ipcp_method_cval (mt, i), *************** ipcp_method_cval_set (ipcp_method mt, in *** 579,592 **** /* Get cval structure of i-th formal of mt. */ static inline struct ipcp_formal * ! ipcp_method_cval (ipcp_method mt, int info_type) { return &(((struct ipa_node *)mt->aux)->ipcp_cval[info_type]); } /* Set type of cval structure of formal i of mt to cval_type. */ static inline void ! ipcp_method_cval_set_cvalue_type (ipcp_method mt, int i, enum Cvalue_type cval_type) { ((struct ipa_node *)mt->aux)->ipcp_cval[i].cvalue_type = cval_type; --- 700,713 ---- /* Get cval structure of i-th formal of mt. */ static inline struct ipcp_formal * ! ipcp_method_cval (ipa_method mt, int info_type) { return &(((struct ipa_node *)mt->aux)->ipcp_cval[info_type]); } /* Set type of cval structure of formal i of mt to cval_type. */ static inline void ! ipcp_method_cval_set_cvalue_type (ipa_method mt, int i, enum Cvalue_type cval_type) { ((struct ipa_node *)mt->aux)->ipcp_cval[i].cvalue_type = cval_type; *************** ipcp_method_cval_set_cvalue_type (ipcp_m *** 594,673 **** /* Returns whether i-th formal of mt is modified in mt. */ static inline bool ! ipcp_method_is_modified (ipcp_method mt, int i) { ! return ((struct ipa_node *)mt->aux)->ipcp_mod[i].mod; } /* Get param tree of i-th formal of mt. */ static inline tree ! ipcp_method_get_tree (ipcp_method mt, int i) { ! return ((struct ipa_node *)mt->aux)->ipcp_param_tree[i].param_tree; } /* Create tree map structure of mt. */ static inline void ! ipcp_method_tree_map_create (ipcp_method mt) { ! ((struct ipa_node *)mt->aux)->ipcp_param_tree = ! xcalloc (ipcp_method_formal_count (mt), sizeof (struct ipcp_tree_map)); } /* Create modify structure of mt. */ static inline void ! ipcp_method_modify_create (ipcp_method mt) { ! ((struct ipa_node *)mt->aux)->ipcp_mod = ! xcalloc (ipcp_method_formal_count (mt), sizeof (struct ipcp_modify)); } /* Set modify of i-th formal of mt. */ static inline void ! ipcp_method_modify_set (ipcp_method mt, int i, bool val) { ! ((struct ipa_node *)mt->aux)->ipcp_mod[i].mod = val; } static void ! ipa_cloned_create (ipcp_method orig_node, ipcp_method new_node) { ipa_node_create (new_node); ipcp_method_set_orig_node (new_node, orig_node); ! ipcp_method_formal_compute_count (new_node); ! ipcp_method_compute_tree_map (new_node); } /* Returning the parameter index of the ptree. */ static int ! ipcp_method_tree_map (ipcp_method mt, tree ptree) { int i, count; ! count = ipcp_method_formal_count (mt); for (i = 0; i < count; i++) ! if (((struct ipa_node *)mt->aux)->ipcp_param_tree[i].param_tree == ptree) return i; return -1; } ! /* Inserting the method's PARM DECL trees to the ipcp_param_tree array. */ static void ! ipcp_method_compute_tree_map (ipcp_method mt) { tree fndecl; tree fnargs; tree parm; int param_num; ! ipcp_method_tree_map_create (mt); fndecl = mt->decl; fnargs = DECL_ARGUMENTS (fndecl); param_num = 0; for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) { ! ((struct ipa_node *)mt->aux)->ipcp_param_tree[param_num].param_tree = parm; param_num++; } } --- 715,794 ---- /* Returns whether i-th formal of mt is modified in mt. */ static inline bool ! ipa_method_is_modified (ipa_method mt, int i) { ! return ((struct ipa_node *)mt->aux)->ipa_mod[i].mod; } /* Get param tree of i-th formal of mt. */ static inline tree ! ipa_method_get_tree (ipa_method mt, int i) { ! return ((struct ipa_node *)mt->aux)->ipa_param_tree[i].param_tree; } /* Create tree map structure of mt. */ static inline void ! ipa_method_tree_map_create (ipa_method mt) { ! ((struct ipa_node *)mt->aux)->ipa_param_tree = ! xcalloc (ipa_method_formal_count (mt), sizeof (struct ipa_tree_map)); } /* Create modify structure of mt. */ static inline void ! ipa_method_modify_create (ipa_method mt) { ! ((struct ipa_node *)mt->aux)->ipa_mod = ! xcalloc (ipa_method_formal_count (mt), sizeof (struct ipa_modify)); } /* Set modify of i-th formal of mt. */ static inline void ! ipa_method_modify_set (ipa_method mt, int i, bool val) { ! ((struct ipa_node *)mt->aux)->ipa_mod[i].mod = val; } static void ! ipa_cloned_create (ipa_method orig_node, ipa_method new_node) { ipa_node_create (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); } /* Returning the parameter index of the ptree. */ static int ! ipa_method_tree_map (ipa_method mt, tree ptree) { int i, count; ! count = ipa_method_formal_count (mt); for (i = 0; i < count; i++) ! if (((struct ipa_node *)mt->aux)->ipa_param_tree[i].param_tree == ptree) return i; return -1; } ! /* Inserting the method's PARM DECL trees to the ipa_param_tree array. */ static void ! ipa_method_compute_tree_map (ipa_method mt) { tree fndecl; tree fnargs; tree parm; int param_num; ! ipa_method_tree_map_create (mt); fndecl = mt->decl; fnargs = DECL_ARGUMENTS (fndecl); param_num = 0; for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) { ! ((struct ipa_node *)mt->aux)->ipa_param_tree[param_num].param_tree = parm; param_num++; } } *************** ipcp_cval_meet (struct ipcp_formal *cval *** 715,721 **** /* Given the jump function, computes the value of cval. */ static void ! ipcp_cval_compute (struct ipcp_formal *cval,ipcp_method mt, enum Jfunc_type type, union info *info_type) { if (type == UNKNOWN_IPATYPE) --- 836,842 ---- /* Given the jump function, computes the value of cval. */ static void ! ipcp_cval_compute (struct ipcp_formal *cval,ipa_method mt, enum Jfunc_type type, union info *info_type) { if (type == UNKNOWN_IPATYPE) *************** ipcp_type_is_const (enum Cvalue_type typ *** 783,789 **** /* Counts how many parameters a method has. */ static void ! ipcp_method_formal_compute_count (ipcp_method mt) { tree fndecl; tree fnargs; --- 904,910 ---- /* Counts how many parameters a method has. */ static void ! ipa_method_formal_compute_count (ipa_method mt) { tree fndecl; tree fnargs; *************** ipcp_method_formal_compute_count (ipcp_m *** 795,814 **** param_num = 0; for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) param_num++; ! ipcp_method_formal_count_set (mt, param_num); } /* Initializes the ipcp_cval array with TOP values. */ static void ! ipcp_method_cval_init (ipcp_method mt) { int i; tree parm_tree; ipcp_formal_create (mt); ! for(i = 0; i < ipcp_method_formal_count (mt); i++) { ! parm_tree = ipcp_method_get_tree (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))) --- 916,935 ---- param_num = 0; for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) param_num++; ! ipa_method_formal_count_set (mt, param_num); } /* Initializes the ipcp_cval array with TOP values. */ static void ! ipcp_method_cval_init (ipa_method mt) { int i; tree parm_tree; ipcp_formal_create (mt); ! for(i = 0; i < ipa_method_formal_count (mt); i++) { ! parm_tree = ipa_method_get_tree (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_init (ipcp_method mt) *** 820,841 **** /* Called by walk_tree. In the case a paramer is modified within the method,the appropriate entry is ! updated in the ipcp_mod array. */ static tree ! ipcp_modify_walk_tree (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data) { tree t = *tp; int i, j; ! ipcp_method mt = (ipcp_method)data; switch (TREE_CODE (t)) { case MODIFY_EXPR: if (TREE_CODE(TREE_OPERAND (t, 0)) == PARM_DECL) { ! i = ipcp_method_tree_map (mt, TREE_OPERAND (t, 0)); ! ipcp_method_modify_set (mt, i, true); } break; case ADDR_EXPR: --- 941,962 ---- /* Called by walk_tree. In the case a paramer is modified within the method,the appropriate entry is ! updated in the ipa_mod array. */ static tree ! ipa_modify_walk_tree (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data) { tree t = *tp; int i, j; ! ipa_method mt = (ipa_method)data; switch (TREE_CODE (t)) { case MODIFY_EXPR: if (TREE_CODE(TREE_OPERAND (t, 0)) == PARM_DECL) { ! i = ipa_method_tree_map (mt, TREE_OPERAND (t, 0)); ! ipa_method_modify_set (mt, i, true); } break; case ADDR_EXPR: *************** ipcp_modify_walk_tree (tree *tp, int *wa *** 844,857 **** if( TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL ) { ! i = ipcp_method_tree_map (mt, TREE_OPERAND (t, 0)); ! ipcp_method_modify_set (mt, i, true); } break; case ASM_EXPR: /* Asm code could modify any of the parameters. */ ! for (j = 0; j < ipcp_method_formal_count (mt); j++) ! ipcp_method_modify_set (mt, j, true); break; default: break; --- 965,978 ---- if( TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL ) { ! i = ipa_method_tree_map (mt, TREE_OPERAND (t, 0)); ! ipa_method_modify_set (mt, i, 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); break; default: break; *************** ipcp_modify_walk_tree (tree *tp, int *wa *** 859,879 **** return NULL; } ! /* Initializes the ipcp_mod array. */ static void ! ipcp_method_modify_init (ipcp_method mt) { int i, count; ! ipcp_method_modify_create (mt); ! count = ipcp_method_formal_count (mt); for(i = 0; i < count; i++) ! ipcp_method_modify_set (mt, i, false); } /* The modify computation driver. */ static void ! ipcp_method_compute_modify (ipcp_method mt) { tree decl; tree body; --- 980,1000 ---- return NULL; } ! /* Initializes the ipa_mod array. */ static void ! ipa_method_modify_init (ipa_method 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. */ static void ! ipa_method_compute_modify (ipa_method mt) { tree decl; tree body; *************** ipcp_method_compute_modify (ipcp_method *** 883,897 **** block_stmt_iterator bsi; tree stmt; ! ipcp_method_modify_init (mt); decl = mt->decl; /* ??? Handle pending sizes case. Set all parameters of the method to be modified. */ if (DECL_UNINLINABLE (decl)) { ! count = ipcp_method_formal_count (mt); for (j = 0; j < count; j++) ! ipcp_method_modify_set (mt, j, true); return; } body = DECL_SAVED_TREE (decl); --- 1004,1018 ---- block_stmt_iterator bsi; tree stmt; ! ipa_method_modify_init (mt); decl = mt->decl; /* ??? Handle pending sizes case. Set all parameters of the method to be modified. */ if (DECL_UNINLINABLE (decl)) { ! count = ipa_method_formal_count (mt); for (j = 0; j < count; j++) ! ipa_method_modify_set (mt, j, true); return; } body = DECL_SAVED_TREE (decl); *************** ipcp_method_compute_modify (ipcp_method *** 903,909 **** for (bsi = bsi_start (bb); ! bsi_end_p (bsi); bsi_next (&bsi)) { stmt = bsi_stmt (bsi); ! ipcp_modify_walk_tree_1 (&stmt, (void *)mt); } } } --- 1024,1030 ---- for (bsi = bsi_start (bb); ! bsi_end_p (bsi); bsi_next (&bsi)) { stmt = bsi_stmt (bsi); ! ipa_modify_walk_tree_1 (&stmt, (void *)mt); } } } *************** ipcp_method_compute_modify (ipcp_method *** 911,934 **** /* Walks tp to find if there's modification to any of the parameters. */ static void ! ipcp_modify_walk_tree_1 (tree *tp, void *data) { ! walk_tree (tp, ipcp_modify_walk_tree, data, NULL); } ! /* ipcp_jump_func interface. */ /* Get type of jump function jf. */ static inline enum Jfunc_type ! get_type (struct ipcp_jump_func *jf) { return jf->type; } /* Get info type of jump function jf. */ static inline union info * ! ipcp_jf_get_info_type (struct ipcp_jump_func *jf) { return &(jf->info_type); } --- 1032,1055 ---- /* Walks tp to find if there's modification to any of the parameters. */ static void ! ipa_modify_walk_tree_1 (tree *tp, void *data) { ! walk_tree (tp, ipa_modify_walk_tree, data, NULL); } ! /* ipa_jump_func interface. */ /* Get type of jump function jf. */ static inline enum Jfunc_type ! get_type (struct ipa_jump_func *jf) { return jf->type; } /* Get info type of jump function jf. */ static inline union info * ! ipa_jf_get_info_type (struct ipa_jump_func *jf) { return &(jf->info_type); } *************** build_const_val (union info *cvalue, enu *** 1044,1050 **** /* Build the constant tree and call constant_val_insert(). */ static void ! ipcp_propagate_const (ipcp_method mt, int param, union info *cvalue, enum Cvalue_type type) { tree fndecl; --- 1165,1171 ---- /* Build the constant tree and call constant_val_insert(). */ static void ! ipcp_propagate_const (ipa_method mt, int param, union info *cvalue, enum Cvalue_type type) { tree fndecl; *************** ipcp_propagate_const (ipcp_method mt, in *** 1055,1061 **** fprintf (dump_file, "propagating const to %s\n", cgraph_node_name (mt)); fndecl = mt->decl; ! parm_tree = ipcp_method_get_tree (mt, param); if (type == CONST_VALUE_INT) const_val = build_int_cst_wide (NULL_TREE, cvalue->int_value.low, cvalue->int_value.high); --- 1176,1182 ---- fprintf (dump_file, "propagating const to %s\n", cgraph_node_name (mt)); fndecl = mt->decl; ! parm_tree = ipa_method_get_tree (mt, param); if (type == CONST_VALUE_INT) const_val = build_int_cst_wide (NULL_TREE, cvalue->int_value.low, cvalue->int_value.high); *************** ipcp_propagate_const (ipcp_method mt, in *** 1068,1107 **** constant_val_insert (fndecl, parm_tree, const_val); } ! /* Initialization and computation of IPCP data structures. It is an intraprocedural ! analysis of methods,which gathers information to be propagated later on. */ static void ! ipcp_init_stage (void) { ! ipcp_method node; ! ipcp_callsite cs; for (node = cgraph_nodes; node; node = node->next) { ! ipcp_method_formal_compute_count (node); ! ipcp_method_compute_tree_map (node); ! ipcp_method_cval_init (node); ! ipcp_method_compute_modify (node); } for (node = cgraph_nodes; node; node = node->next) { /* building jump functions */ for (cs = node->callees; cs; cs = cs->next_callee) { ! ipcp_callsite_compute_count (cs); ! if (ipcp_callsite_param_count (cs) ! != ipcp_method_formal_count (cs->callee)) { /* Handles the cases of functions with a variable number of parameters. */ ! ipcp_callsite_param_count_set (cs, 0); ! ipcp_method_formal_count_set (cs->callee, 0); } else ! ipcp_callsite_compute_param (cs); ! } } } --- 1189,1246 ---- constant_val_insert (fndecl, parm_tree, const_val); } ! /* Initialization and computation of IPA data structures. It is an intraprocedural ! analysis of methods, which gathers information to be propagated later on. */ static void ! ipa_init_stage (enum ipa_analysis_type type) { ! ipa_method node; ! ipa_callsite cs; for (node = cgraph_nodes; node; node = node->next) { ! ipa_method_formal_compute_count (node); ! ipa_method_compute_tree_map (node); ! ipa_method_compute_modify (node); ! if (type&IPA_CONSTANT_PROP) ! ipcp_method_cval_init (node); ! if (type&IPA_ALIAS_ANALYSIS) ! { ! ipaa_method_compute_num_pairs (node); ! ipaa_method_alias_init (node); ! } } for (node = cgraph_nodes; node; node = node->next) { /* building jump functions */ for (cs = node->callees; cs; cs = cs->next_callee) { ! ipa_callsite_compute_count (cs); ! if (type&IPA_ALIAS_ANALYSIS) ! ipaa_callsite_compute_num_pairs (cs); ! if (ipa_callsite_param_count (cs) ! != ipa_method_formal_count (cs->callee)) { /* Handles the cases of functions with a variable number of parameters. */ ! ipa_callsite_param_count_set (cs, 0); ! ipa_method_formal_count_set (cs->callee, 0); ! if (type&IPA_ALIAS_ANALYSIS) ! ipaa_method_set_num_pairs_args (cs->callee, 0); } else ! { ! ipa_callsite_compute_param (cs); ! if (type&IPA_ALIAS_ANALYSIS) ! ipaa_callsite_alias_init (cs); ! } ! } ! if (type&IPA_ALIAS_ANALYSIS) ! /* initialize aliasing info at callsites by doing ! intraprocedural aliasing analysis. */ ! ipaa_callsites_init_aliasing (node); } } *************** static bool *** 1121,1133 **** ipcp_after_propagate (void) { int i, count; ! ipcp_method node; bool prop_again; prop_again = false; for (node = cgraph_nodes; node; node = node->next) { ! count = ipcp_method_formal_count (node); for(i = 0; i < count; i++) if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) == TOP) { --- 1260,1272 ---- ipcp_after_propagate (void) { int i, count; ! ipa_method node; bool prop_again; prop_again = false; for (node = cgraph_nodes; node; node = node->next) { ! count = ipa_method_formal_count (node); for(i = 0; i < count; i++) if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) == TOP) { *************** ipcp_propagate_stage (void) *** 1146,1180 **** int i; struct ipcp_formal cval1 = {0, {{0, 0}}}, cval = {0, {{0, 0}}}; struct ipcp_formal *cval2; ! ipcp_method mt, callee; ! ipcp_callsite cs; ! struct ipcp_jump_func *jump_func; enum Jfunc_type type; union info *info_type; ! ipcp_methodlist_p wl; int count; ! wl = ipcp_methodlist_init (); ! while (ipcp_methodlist_not_empty (wl)) { ! mt = ipcp_remove_method (&wl); for (cs = mt->callees; cs; cs = cs->next_callee) { ! callee = ipcp_callsite_callee (cs); ! count = ipcp_callsite_param_count (cs); for (i = 0; i < count; i++) { ! jump_func = ipcp_callsite_param (cs, i); type = get_type (jump_func); ! info_type = ipcp_jf_get_info_type (jump_func); ipcp_cval_compute (&cval1, mt, type, info_type); ! callee = ipcp_callsite_callee (cs); 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); ! ipcp_add_method (&wl, callee); } } } --- 1285,1319 ---- int i; struct ipcp_formal cval1 = {0, {{0, 0}}}, cval = {0, {{0, 0}}}; struct ipcp_formal *cval2; ! ipa_method mt, callee; ! ipa_callsite cs; ! struct ipa_jump_func *jump_func; enum Jfunc_type type; union info *info_type; ! ipa_methodlist_p wl; int count; ! wl = ipa_methodlist_init (); ! while (ipa_methodlist_not_empty (wl)) { ! mt = ipa_remove_method (&wl); for (cs = mt->callees; cs; cs = cs->next_callee) { ! callee = ipa_callsite_callee (cs); ! count = ipa_callsite_param_count (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); ! callee = ipa_callsite_callee (cs); 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); } } } *************** ipcp_replace_map_create (enum Cvalue_typ *** 1227,1237 **** static void ipcp_insert_stage (void) { ! ipcp_method node, node1 = NULL; int i, const_param; union info *cvalue; varray_type redirect_callers, replace_trees; ! ipcp_callsite cs; int node_callers, count; tree parm_tree; enum Cvalue_type type; --- 1366,1376 ---- static void ipcp_insert_stage (void) { ! ipa_method node, node1 = NULL; int i, const_param; union info *cvalue; varray_type redirect_callers, replace_trees; ! ipa_callsite cs; int node_callers, count; tree parm_tree; enum Cvalue_type type; *************** ipcp_insert_stage (void) *** 1244,1250 **** if (ipcp_method_dont_insert_const (node)) continue; const_param=0; ! count = ipcp_method_formal_count (node); for(i = 0; i < count; i++) { type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)); --- 1383,1389 ---- if (ipcp_method_dont_insert_const (node)) continue; const_param=0; ! count = ipa_method_formal_count (node); for(i = 0; i < count; i++) { type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)); *************** ipcp_insert_stage (void) *** 1260,1266 **** if (ipcp_type_is_const (type)) { cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i)); ! parm_tree = ipcp_method_get_tree (node, i); replace_param = ipcp_replace_map_create (type, parm_tree, cvalue); VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param); } --- 1399,1405 ---- if (ipcp_type_is_const (type)) { cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i)); ! parm_tree = ipa_method_get_tree (node, i); replace_param = ipcp_replace_map_create (type, parm_tree, cvalue); VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param); } *************** ipcp_insert_stage (void) *** 1290,1296 **** if (ipcp_type_is_const (type)) { cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i)); ! parm_tree = ipcp_method_get_tree (node, i); if ( type != CONST_VALUE_INT_REF && type != CONST_VALUE_FLOAT_REF && !TREE_READONLY (parm_tree)) ipcp_propagate_const (node1, i, cvalue, type); --- 1429,1435 ---- 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_INT_REF && type != CONST_VALUE_FLOAT_REF && !TREE_READONLY (parm_tree)) ipcp_propagate_const (node1, i, cvalue, type); *************** ipcp_insert_stage (void) *** 1305,1311 **** static void ipa_nodes_create (void) { ! ipcp_method node; for (node = cgraph_nodes; node; node = node->next) ipa_node_create (node); --- 1444,1450 ---- static void ipa_nodes_create (void) { ! ipa_method node; for (node = cgraph_nodes; node; node = node->next) ipa_node_create (node); *************** ipa_nodes_create (void) *** 1315,1322 **** static void ipa_edges_create (void) { ! ipcp_method node; ! ipcp_callsite cs; for (node = cgraph_nodes; node; node = node->next) for (cs = node->callees; cs; cs = cs->next_callee) --- 1454,1461 ---- static void ipa_edges_create (void) { ! ipa_method node; ! ipa_callsite cs; for (node = cgraph_nodes; node; node = node->next) for (cs = node->callees; cs; cs = cs->next_callee) *************** ipa_edges_create (void) *** 1327,1333 **** static void ipa_nodes_free (void) { ! ipcp_method node; for (node = cgraph_nodes; node; node = node->next) { --- 1466,1472 ---- static void ipa_nodes_free (void) { ! ipa_method node; for (node = cgraph_nodes; node; node = node->next) { *************** ipa_nodes_free (void) *** 1340,1347 **** static void ipa_edges_free (void) { ! ipcp_method node; ! ipcp_callsite cs; for (node = cgraph_nodes; node; node = node->next) for (cs = node->callees; cs; cs = cs->next_callee) --- 1479,1486 ---- static void ipa_edges_free (void) { ! ipa_method node; ! ipa_callsite cs; for (node = cgraph_nodes; node; node = node->next) for (cs = node->callees; cs; cs = cs->next_callee) *************** ipa_edges_free (void) *** 1351,1396 **** } } - /* The IPCP driver. */ - void - ipcp_driver (void) - { - if (dump_file) - fprintf (dump_file, "\nIPA constant propagation start:\n"); - ipa_nodes_create (); - ipa_edges_create (); - /* 1. Call the init stage to initialize - the ipa_node and ipa_edge structures. */ - ipcp_init_stage (); - if (dump_file) - { - fprintf (dump_file, "\nIPA structures before propagation:\n"); - ipcp_structures_print (dump_file); - } - /* 2. Do the interprocedural propagation. */ - ipcp_iterate_stage (); - if (dump_file) - { - fprintf (dump_file, "\nIPA structures after propagation:\n"); - ipcp_structures_print (dump_file); - } - /* 3. Insert the constants found to the functions. */ - ipcp_insert_stage (); - /* Free all IPCP structures. */ - ipcp_free (); - ipa_nodes_free (); - ipa_edges_free (); - if (dump_file) - fprintf (dump_file, "\nIPA constant propagation end\n"); - cgraph_remove_unreachable_nodes (true, NULL); - } - /* Frees the ipcp_method's IPCP data structures. */ static void ! ipcp_free (void) { ! ipcp_method node; ! ipcp_callsite cs; for (node = cgraph_nodes; node; node = node->next) { --- 1490,1501 ---- } } /* Frees the ipcp_method's IPCP data structures. */ static void ! ipa_free (void) { ! ipa_method node; ! ipa_callsite cs; for (node = cgraph_nodes; node; node = node->next) { *************** ipcp_free (void) *** 1398,1419 **** continue; if (((struct ipa_node *)node->aux)->ipcp_cval) free (((struct ipa_node *)node->aux)->ipcp_cval); ! if (((struct ipa_node *)node->aux)->ipcp_param_tree) ! free (((struct ipa_node *)node->aux)->ipcp_param_tree); ! if (((struct ipa_node *)node->aux)->ipcp_mod) ! free (((struct ipa_node *)node->aux)->ipcp_mod); for (cs = node->callees; cs; cs = cs->next_callee) { if (cs->aux) ! if (((struct ipa_edge *)cs->aux)->ipcp_param_map) ! free (((struct ipa_edge *)cs->aux)->ipcp_param_map); } } } /* Check conditions to forbid constant insertion to the function. */ static bool ! ipcp_method_dont_insert_const (ipcp_method mt) { /* ??? Handle pending sizes case. */ if (DECL_UNINLINABLE (mt->decl)) --- 1503,1530 ---- continue; if (((struct ipa_node *)node->aux)->ipcp_cval) free (((struct ipa_node *)node->aux)->ipcp_cval); ! if (((struct ipa_node *)node->aux)->ipa_param_tree) ! free (((struct ipa_node *)node->aux)->ipa_param_tree); ! if (((struct ipa_node *)node->aux)->ipa_mod) ! free (((struct ipa_node *)node->aux)->ipa_mod); ! if (((struct ipa_node *)node->aux)->ipaa_aliasing) ! free (((struct ipa_node *)node->aux)->ipaa_aliasing); for (cs = node->callees; cs; cs = cs->next_callee) { if (cs->aux) ! { ! if (((struct ipa_edge *)cs->aux)->ipa_param_map) ! free (((struct ipa_edge *)cs->aux)->ipa_param_map); ! if (((struct ipa_edge *)cs->aux)->ipaa_aliasing) ! free (((struct ipa_edge *)cs->aux)->ipaa_aliasing); ! } } } } /* Check conditions to forbid constant insertion to the function. */ static bool ! ipcp_method_dont_insert_const (ipa_method mt) { /* ??? Handle pending sizes case. */ if (DECL_UNINLINABLE (mt->decl)) *************** ipcp_asm_walk_tree (tree *tp, int *walk_ *** 1444,1450 **** /* Finds if there are any asm expr in the function. */ static bool ! ipcp_method_contains_asm (ipcp_method mt) { tree decl; tree body; --- 1555,1561 ---- /* Finds if there are any asm expr in the function. */ static bool ! ipcp_method_contains_asm (ipa_method mt) { tree decl; tree body; *************** ipcp_asm_walk_tree_1 (tree *tp) *** 1479,1485 **** return walk_tree (tp, ipcp_asm_walk_tree, NULL, NULL); } - /* Debugging interface. */ /* Prints all IPCP data structures. */ --- 1590,1595 ---- *************** static void *** 1487,1494 **** ipcp_structures_print (FILE *f) { ipcp_method_cval_print (f); ! ipcp_method_tree_print (f); ! ipcp_method_modify_print (f); ipcp_callsite_param_print (f); } --- 1597,1604 ---- ipcp_structures_print (FILE *f) { ipcp_method_cval_print (f); ! ipa_method_tree_print (f); ! ipa_method_modify_print (f); ipcp_callsite_param_print (f); } *************** ipcp_structures_print (FILE *f) *** 1496,1502 **** static void ipcp_method_cval_print (FILE *f) { ! ipcp_method node; int i, count; ipcp_int* cvalue; --- 1606,1612 ---- static void ipcp_method_cval_print (FILE *f) { ! ipa_method node; int i, count; ipcp_int* cvalue; *************** ipcp_method_cval_print (FILE *f) *** 1504,1510 **** for (node = cgraph_nodes; node; node = node->next) { fprintf (f, "printing cvals %s:\n", cgraph_node_name (node)); ! count = ipcp_method_formal_count (node); for(i = 0; i < count; i++) { if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) --- 1614,1620 ---- for (node = cgraph_nodes; node; node = node->next) { fprintf (f, "printing cvals %s:\n", cgraph_node_name (node)); ! count = ipa_method_formal_count (node); for(i = 0; i < count; i++) { if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) *************** ipcp_method_cval_print (FILE *f) *** 1536,1557 **** } } ! /* Prints ipcp_tree_map data structures. */ static void ! ipcp_method_tree_print (FILE *f) { int i, count; tree temp; ! ipcp_method node; 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 = ipcp_method_formal_count (node); for (i = 0; i < count; i++) { ! temp = ipcp_method_get_tree (node, i); if (TREE_CODE (temp) == PARM_DECL) fprintf(f, " param [%d] : %s\n", i, (*lang_hooks.decl_printable_name) (temp, 2)); --- 1646,1667 ---- } } ! /* Prints ipa_tree_map data structures. */ static void ! ipa_method_tree_print (FILE *f) { int i, count; tree temp; ! ipa_method node; 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); for (i = 0; i < count; i++) { ! temp = ipa_method_get_tree (node, i); if (TREE_CODE (temp) == PARM_DECL) fprintf(f, " param [%d] : %s\n", i, (*lang_hooks.decl_printable_name) (temp, 2)); *************** ipcp_method_tree_print (FILE *f) *** 1565,1586 **** } } ! /* Printf ipcp_modify data structures. */ static void ! ipcp_method_modify_print (FILE *f) { int i, count; bool temp; ! ipcp_method node; fprintf(f, "\nMODIFY PRINT\n"); for (node = cgraph_nodes; node; node = node->next) { fprintf (f, "method %s :: \n", cgraph_node_name (node)); ! count = ipcp_method_formal_count (node); for (i = 0; i < count; i++) { ! temp = ipcp_method_is_modified (node, i); if (temp) fprintf (f, " param [%d] true \n", i); else --- 1675,1696 ---- } } ! /* Printf ipa_modify data structures. */ static void ! ipa_method_modify_print (FILE *f) { int i, count; bool temp; ! ipa_method node; 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); for (i = 0; i < count; i++) { ! temp = ipa_method_is_modified (node, i); if (temp) fprintf (f, " param [%d] true \n", i); else *************** ipcp_method_modify_print (FILE *f) *** 1589,1602 **** } } ! /* Prints ipcp_jump_func data structures. */ static void ipcp_callsite_param_print (FILE *f) { ! ipcp_method node; int i, count; ! ipcp_callsite cs; ! struct ipcp_jump_func *jump_func; enum Jfunc_type type; ipcp_int* info_type_int; REAL_VALUE_TYPE info_type_float; --- 1699,1712 ---- } } ! /* Prints ipa_jump_func data structures. */ static void ipcp_callsite_param_print (FILE *f) { ! ipa_method node; int i, count; ! ipa_callsite cs; ! struct ipa_jump_func *jump_func; enum Jfunc_type type; ipcp_int* info_type_int; REAL_VALUE_TYPE info_type_float; *************** ipcp_callsite_param_print (FILE *f) *** 1608,1617 **** { fprintf (f, "callsite %s ", cgraph_node_name (node)); fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee)); ! count = ipcp_callsite_param_count (cs); for (i = 0; i < count; i++) { ! jump_func = ipcp_callsite_param (cs, i); type = get_type(jump_func); fprintf (f, " param %d: ", i); --- 1718,1727 ---- { fprintf (f, "callsite %s ", cgraph_node_name (node)); fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee)); ! count = ipa_callsite_param_count (cs); for (i = 0; i < count; i++) { ! jump_func = ipa_callsite_param (cs, i); type = get_type(jump_func); fprintf (f, " param %d: ", i); *************** ipcp_callsite_param_print (FILE *f) *** 1619,1625 **** fprintf (f, "UNKNOWN\n"); else if (type == CONST_IPATYPE_INT) { ! info_type_int = &((ipcp_jf_get_info_type (jump_func))->int_value); fprintf (f, "CONST INT : "); fprintf (f, " "HOST_WIDE_INT_PRINT_DEC " "HOST_WIDE_INT_PRINT_DEC" \n", --- 1729,1735 ---- fprintf (f, "UNKNOWN\n"); else if (type == CONST_IPATYPE_INT) { ! info_type_int = &((ipa_jf_get_info_type (jump_func))->int_value); fprintf (f, "CONST INT : "); fprintf (f, " "HOST_WIDE_INT_PRINT_DEC " "HOST_WIDE_INT_PRINT_DEC" \n", *************** ipcp_callsite_param_print (FILE *f) *** 1628,1634 **** else if (type == CONST_IPATYPE_FLOAT) { char string[100]; ! info_type_float = (ipcp_jf_get_info_type (jump_func))->float_value; fprintf (f, "CONST FLOAT "); real_to_decimal (string, &info_type_float, sizeof (string), 0, 1); --- 1738,1744 ---- else if (type == CONST_IPATYPE_FLOAT) { char string[100]; ! info_type_float = (ipa_jf_get_info_type (jump_func))->float_value; fprintf (f, "CONST FLOAT "); real_to_decimal (string, &info_type_float, sizeof (string), 0, 1); *************** ipcp_callsite_param_print (FILE *f) *** 1639,1645 **** else if (type == FORMAL_IPATYPE) { fprintf (f, "FORMAL : "); ! fprintf (f, "%d\n", ipcp_jf_get_info_type (jump_func)->formal_id ); } } } --- 1749,1755 ---- else if (type == FORMAL_IPATYPE) { fprintf (f, "FORMAL : "); ! fprintf (f, "%d\n", ipa_jf_get_info_type (jump_func)->formal_id ); } } } *************** ipcp_callsite_param_print (FILE *f) *** 1650,1657 **** static void ipcp_update_callgraph (void) { ! ipcp_method node, orig_callee; ! ipcp_callsite cs; for (node = cgraph_nodes; node; node = node->next) { --- 1760,1767 ---- static void ipcp_update_callgraph (void) { ! ipa_method node, orig_callee; ! ipa_callsite cs; for (node = cgraph_nodes; node; node = node->next) { *************** ipcp_update_callgraph (void) *** 1675,1698 **** /* Retruns true if this callsite should be redirected to the orig callee (instead of the cloned one). */ static bool ! ipcp_redirect (ipcp_callsite cs) { ! ipcp_method caller, callee, orig_callee; int i, count; ! struct ipcp_jump_func *jump_func; enum Jfunc_type type; enum Cvalue_type cval_type; caller = cs->caller; callee = cs->callee; orig_callee = ipcp_method_orig_node (callee); ! count = ipcp_method_formal_count (orig_callee); for (i = 0; i < count; i++) { cval_type = ipcp_cval_get_cvalue_type (ipcp_method_cval (orig_callee, i)); if (ipcp_type_is_const (cval_type)) { ! jump_func = ipcp_callsite_param (cs, i); type = get_type (jump_func); if (type != CONST_IPATYPE_INT && type != CONST_IPATYPE_FLOAT && type != CONST_IPATYPE_INT_REF && type != CONST_IPATYPE_FLOAT_REF) --- 1785,1808 ---- /* Retruns true if this callsite should be redirected to the orig callee (instead of the cloned one). */ static bool ! ipcp_redirect (ipa_callsite cs) { ! ipa_method caller, callee, orig_callee; int i, count; ! struct ipa_jump_func *jump_func; enum Jfunc_type type; enum Cvalue_type cval_type; caller = cs->caller; callee = cs->callee; orig_callee = ipcp_method_orig_node (callee); ! count = ipa_method_formal_count (orig_callee); for (i = 0; i < count; i++) { cval_type = ipcp_cval_get_cvalue_type (ipcp_method_cval (orig_callee, i)); if (ipcp_type_is_const (cval_type)) { ! jump_func = ipa_callsite_param (cs, i); type = get_type (jump_func); if (type != CONST_IPATYPE_INT && type != CONST_IPATYPE_FLOAT && type != CONST_IPATYPE_INT_REF && type != CONST_IPATYPE_FLOAT_REF) *************** struct tree_opt_pass pass_ipa_cp = *** 1730,1732 **** --- 1840,2843 ---- 0 /* letter */ }; + /* ipaa_method interface. */ + + /* Create ipaa_alias_info for method mt. */ + static inline void + ipaa_method_create_alias_info (ipa_method mt) + { + ((struct ipa_node *)mt->aux)->ipaa_aliasing = + xcalloc (ipaa_method_get_num_pairs_args (mt), sizeof (ipaa_alias_info)); + } + + /* Create and initialize the ipaa_alias_info of the method MT + with DO_NOT_KNOW values. */ + static void + ipaa_method_alias_init (ipa_method mt) + { + int i; + + ipaa_method_create_alias_info (mt); + for(i = 0; i < ipaa_method_get_num_pairs_args (mt); i++) + ipaa_method_set_alias_info (mt, DO_NOT_KNOW, i); + } + + /* Set ipaa_num_pairs_args to I. */ + static inline + void ipaa_method_set_num_pairs_args (ipa_method mt, int i) + { + ((struct ipa_node *)mt->aux)->ipaa_num_pairs_args = i; + } + + /* Return ipaa_num_pairs_args. */ + static inline + int ipaa_method_get_num_pairs_args (ipa_method mt) + { + return ((struct ipa_node *)mt->aux)->ipaa_num_pairs_args; + } + + /* Counts how many pairs of parameters the method MT has. */ + static inline void + ipaa_method_compute_num_pairs (ipa_method mt) + { + int n = ipa_method_formal_count (mt); + ipaa_method_set_num_pairs_args (mt, n*(n-1)/2); + } + + /* Set ipaa_alias_info for the pair of formals (I,J). */ + static inline void + ipaa_method_set_pair_alias_info (ipa_method mt, + ipaa_alias_info alias, int i, int j) + { + int n = ipa_method_formal_count (mt); + int k = (i*n) - ((i+1)*i)/2 + (j-i-1); + gcc_assert (j > i && i >= 0 && j >= 1 && i < (n-1) && j < n); + ((struct ipa_node *)mt->aux)->ipaa_aliasing[k] = alias; + } + + /* Get ipaa_alias_info for the pair of formals (i,j). */ + static inline ipaa_alias_info + ipaa_method_get_pair_alias_info (ipa_method mt, int i, int j) + { + int n = ipa_method_formal_count (mt); + int k = (i*n) - ((i+1)*i)/2 + (j-i-1); + gcc_assert (j > i && i >= 0 && j >= 1 && i < (n-1) && j < n); + return ((struct ipa_node *)mt->aux)->ipaa_aliasing[k]; + } + + /* Set I value of the array ipaa_aliasing to be equal to ALIAS. */ + static inline void + ipaa_method_set_alias_info (ipa_method mt, ipaa_alias_info alias, int i) + { + int n = ipaa_method_get_num_pairs_args (mt); + gcc_assert (i >= 0 && i < n); + ((struct ipa_node *)mt->aux)->ipaa_aliasing[i] = alias; + } + + /* Return I value of the array ipaa_aliasing. */ + static inline ipaa_alias_info ipaa_method_get_alias_info (ipa_method mt, int i) + { + int n = ipaa_method_get_num_pairs_args (mt); + gcc_assert (i >= 0 && i < n); + return ((struct ipa_node *)mt->aux)->ipaa_aliasing[i]; + } + + /* ipaa_callsite interface. */ + + /* Create ipaa_alias_info for callsite CS. */ + static inline void + ipaa_callsite_create_alias_info (ipa_callsite cs) + { + ((struct ipa_edge *)cs->aux)->ipaa_aliasing = + xcalloc (ipaa_callsite_get_num_pairs_args (cs), sizeof (ipaa_alias_info)); + } + + /* Create and initialize the ipaa_alias_info of the callsite CS + with DO_NOT_KNOW values. */ + static void + ipaa_callsite_alias_init (ipa_callsite cs) + { + int i; + + ipaa_callsite_create_alias_info (cs); + for(i = 0; i < ipaa_callsite_get_num_pairs_args (cs); i++) + ipaa_callsite_set_alias_info (cs, DO_NOT_KNOW, i); + } + + /* Set ipaa_num_pairs_args to I. */ + static inline + void ipaa_callsite_set_num_pairs_args (ipa_callsite cs, int i) + { + ((struct ipa_edge *)cs->aux)->ipaa_num_pairs_args = i; + } + + /* Return ipaa_num_pairs_args. */ + static inline + int ipaa_callsite_get_num_pairs_args (ipa_callsite cs) + { + return ((struct ipa_edge *)cs->aux)->ipaa_num_pairs_args; + } + + /* Counts how many pairs of parameters the callsite CS has. */ + static inline void + ipaa_callsite_compute_num_pairs (ipa_callsite cs) + { + int n = ipa_callsite_param_count (cs); + ipaa_callsite_set_num_pairs_args (cs, n*(n-1)/2); + } + + /* Set ipaa_alias_info for the pair of actual parameters (I,J). */ + static inline void + ipaa_callsite_set_pair_alias_info (ipa_callsite cs, + ipaa_alias_info alias, int i, int j) + { + int n = ipa_callsite_param_count (cs); + int k = (i*n) - ((i+1)*i)/2 + (j-i-1); + gcc_assert (j > i && i >= 0 && j >= 1 && i < (n-1) && j < n); + ((struct ipa_edge *)cs->aux)->ipaa_aliasing[k] = alias; + } + + /* Get ipaa_alias_info for the pair of formals (i,j). */ + static inline ipaa_alias_info + ipaa_callsite_get_pair_alias_info (ipa_callsite cs, int i, int j) + { + int n = ipa_callsite_param_count (cs); + int k = (i*n) - ((i+1)*i)/2 + (j-i-1); + gcc_assert (j > i && i >= 0 && j >= 1 && i < (n-1) && j < n); + return ((struct ipa_edge *)cs->aux)->ipaa_aliasing[k]; + } + + /* Set I value of the array ipaa_aliasing to be equal to ALIAS. */ + static inline void + ipaa_callsite_set_alias_info (ipa_callsite cs, ipaa_alias_info alias, int i) + { + int n = ipaa_callsite_get_num_pairs_args (cs); + gcc_assert (i >= 0 && i < n); + ((struct ipa_edge *)cs->aux)->ipaa_aliasing[i] = alias; + } + + /* Return I value of the array ipaa_aliasing. */ + static inline ipaa_alias_info ipaa_callsite_get_alias_info (ipa_callsite cs, int i) + { + int n = ipaa_callsite_get_num_pairs_args (cs); + gcc_assert (i >= 0 && i < n); + return ((struct ipa_edge *)cs->aux)->ipaa_aliasing[i]; + } + + /* This function compute alias_info for each pair of actual + parametrers of callsite CS. */ + static void + ipaa_callsite_compute_param (ipa_callsite cs) + { + if (ipaa_callsite_get_num_pairs_args (cs) == 0) + return; + ipaa_callsite_alias_init (cs); + } + + /* ipaa_varslist Interface. */ + + /* Create the varslist node. */ + static inline ipaa_varslist_p + ipaa_create_varslist_node (void) + { + return ggc_alloc (sizeof (struct ipaa_varslist)); + } + + /* Check that varslist is not empty. */ + static inline bool + ipaa_varslist_not_empty (ipaa_varslist_p vl) + { + return (vl != NULL); + } + + /* Get var tree from varslist's node. */ + static inline tree + ipaa_varslist_var (ipaa_varslist_p vl) + { + return vl->var_decl; + } + + /* Set var_decl of varslist's node to be equal to var. */ + static inline void + ipaa_varslist_var_set (ipaa_varslist_p vl, tree var) + { + vl->var_decl = var; + } + + /* Get call_expr tree from varslist's node. */ + static inline tree + ipaa_varslist_call_expr (ipaa_varslist_p vl) + { + return vl->call_expr; + } + + /* Set call_expr of varslist's node to be equal to call_expr. */ + static inline void + ipaa_varslist_call_expr_set (ipaa_varslist_p vl, tree call_expr) + { + vl->call_expr = call_expr; + } + + /* Get modified from varslist's node. */ + static inline bool + ipaa_varslist_modified (ipaa_varslist_p vl) + { + return vl->modified; + } + + /* Set modified of varslist's node to be equal to mod. */ + static inline void + ipaa_varslist_modified_set (ipaa_varslist_p vl, bool mod) + { + vl->modified = mod; + } + + /* Get next varslist's node. */ + static inline ipaa_varslist_p + ipaa_varslist_next_var (ipaa_varslist_p vl) + { + return vl->next_var; + } + + /* Sets varslist node vl1 to point to varslist node vl2. */ + static inline void + ipaa_varslist_next_var_set (ipaa_varslist_p vl1, ipaa_varslist_p vl2) + { + vl1->next_var = vl2; + } + + /* Initializing varslist. */ + static ipaa_varslist_p + ipaa_varslist_init (void) + { + return NULL; + } + + /* Adding a var to the varslist. */ + static ipaa_varslist_p + ipaa_add_var (ipaa_varslist_p vl, tree var, tree call_expr) + { + ipaa_varslist_p temp; + + temp = ipaa_create_varslist_node (); + ipaa_varslist_var_set (temp, var); + ipaa_varslist_call_expr_set (temp, call_expr); + ipaa_varslist_modified_set (temp, false); + ipaa_varslist_next_var_set (temp, vl); + return temp; + } + + /* Destroy varslist. */ + static void + ipaa_destroy_varslist (ipaa_varslist_p vl) + { + ipaa_varslist_p p1 = vl, p2; + + while (p1) + { + p2 = ipaa_varslist_next_var (p1); + ggc_free (p1); + p1 = p2; + } + } + + /* Print varslist. */ + static void + ipaa_print_varslist (FILE *f, ipaa_varslist_p vl) + { + ipaa_varslist_p p = vl; + + while (p) + { + fprintf (f, "\nvar %s", IDENTIFIER_POINTER (DECL_NAME (ipaa_varslist_var (p)))); + if (ipaa_varslist_modified (p)) + fprintf (f, " is modified"); + else + fprintf (f, " is not modified"); + p = ipaa_varslist_next_var (p); + } + } + + /* Return false if var is in worklist and was not modified, and true otherwise. */ + static bool + ipaa_varslist_is_modified (tree var, ipaa_varslist_p list) + { + ipaa_varslist_p p = list; + gcc_assert (var != NULL); + while (p) + { + if(ipaa_varslist_var (p) == var) + return ipaa_varslist_modified (p); + p = ipaa_varslist_next_var (p); + } + return true; + } + + /* Starting from node pointed by the LIST, this function returns pointer + to the fisrt node that contain var and NULL otherwise. */ + static ipaa_varslist_p + ipaa_varslist_find_var (tree var, ipaa_varslist_p list) + { + ipaa_varslist_p p = list; + gcc_assert (var != NULL); + while (p) + { + if(ipaa_varslist_var (p) == var) + return p; + p = ipaa_varslist_next_var (p); + } + return NULL; + } + + /* This function return true if ARG is an address of array defined + in function with DECL_NAME CURR_FUNC. In this case ARRAY_NAME contains + the DECL_NAME of array. Otherwise this function returns false. */ + static bool + ipaa_is_address_of_local_array (tree arg, tree* array_decl, tree curr_func) + { + tree arg_0, func; + + *array_decl = NULL; + + if (arg) + { + if(TREE_CODE (arg) == TREE_LIST && + TREE_CODE (TREE_VALUE (arg)) == ADDR_EXPR && + TREE_CODE (TREE_TYPE (TREE_VALUE (arg))) == POINTER_TYPE) + { + if (TREE_INVARIANT (TREE_VALUE (arg))) + { + arg_0 = TREE_OPERAND (TREE_VALUE (arg), 0); + if (TREE_CODE (arg_0) == VAR_DECL) + { + if(TREE_CODE (TREE_TYPE (arg_0)) == ARRAY_TYPE) + { + if(DECL_CONTEXT (arg_0)) + { + if (TREE_CODE (DECL_CONTEXT (arg_0)) == FUNCTION_DECL) + { + func = DECL_NAME (DECL_CONTEXT (arg_0)); + if ( func == curr_func) + { + *array_decl = arg_0; + return true; + } + } + } + } + } + } + } + } + return false; + } + + /* This function returns true if i's arg of callsite cs is non modified + formal of the method mt, and false otherwise. */ + static bool + ipaa_is_non_modified_formal (ipa_callsite cs, int i, ipa_method mt) + { + struct ipa_jump_func *jump_func; + enum Jfunc_type type; + union info *info_type; + + jump_func = ipa_callsite_param (cs, i); + type = get_type (jump_func); + info_type = ipa_jf_get_info_type (jump_func); + + if (type == FORMAL_IPATYPE) + { + if (!ipa_method_is_modified (mt, info_type->formal_id)) + return true; + } + + return false; + } + + /* Prints all IPAA data structures. */ + static void + ipaa_structures_print (FILE *f) + { + ipa_method_tree_print (f); + ipa_method_modify_print (f); + ipaa_method_alias_info_print (f); + ipaa_callsite_alias_info_print (f); + ipaa_callsite_param_trees_print (f); + } + + /* Prints ipcp_cval data structures. */ + static void + ipaa_callsite_alias_info_print (FILE *f) + { + ipa_method node; + ipa_callsite cs; + int i, j, count; + + fprintf(f, "\nALIAS PRINT CALLSITES\n"); + for (node = cgraph_nodes; node; node = node->next) + { + for (cs = node->callees; cs; cs = cs->next_callee) + { + fprintf (f, "callsite %s ", cgraph_node_name (node)); + fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee)); + count = ipa_callsite_param_count (cs); + for(i = 0; i < count - 1; i++) + { + for(j = i + 1; j < count; j++) + { + fprintf (f, "alias_info [%d, %d] = ", i, j); + if (ipaa_callsite_get_pair_alias_info (cs, i, j) == MAY_ALIAS) + fprintf (f, "MAY_ALIAS\n"); + else if (ipaa_callsite_get_pair_alias_info (cs, i, j) == MUST_ALIAS) + fprintf (f, "MUST_ALIAS\n"); + else if (ipaa_callsite_get_pair_alias_info (cs, i, j) == NON_ALIAS) + fprintf (f, "NON_ALIAS\n"); + else + fprintf (f, "DO_NOT_KNOW\n"); + } + } + } + } + } + + /* Prints ipcp_cval data structures. */ + static void + ipaa_method_alias_info_print (FILE *f) + { + ipa_method node; + int i, j, count; + + fprintf(f, "\nALIAS PRINT METHODS\n"); + for (node = cgraph_nodes; node; node = node->next) + { + fprintf (f, "printing alias info for %s\n", cgraph_node_name (node)); + count = ipa_method_formal_count (node); + for(i = 0; i < count - 1; i++) + { + for(j = i + 1; j < count; j++) + { + fprintf (f, "alias_info [%d, %d] = ", i, j); + if (ipaa_method_get_pair_alias_info (node, i, j) == MAY_ALIAS) + fprintf (f, "MAY_ALIAS\n"); + else if (ipaa_method_get_pair_alias_info (node, i, j) == MUST_ALIAS) + fprintf (f, "MUST_ALIAS\n"); + else if (ipaa_method_get_pair_alias_info (node, i, j) == NON_ALIAS) + fprintf (f, "NON_ALIAS\n"); + else /* DO_NOT_KNOW */ + fprintf (f, "DO_NOT_KNOW\n"); + } + } + } + } + + static void ipaa_callsite_addr_local_array_print (FILE *f, tree arg) + { + tree arg_0; + + fprintf(f, "\n"); + fprintf(f, "arg code is: "); + fprintf(f, "%s\n", tree_code_name[(int) TREE_CODE (arg)]); + fprintf(f, "arg value code is: "); + fprintf(f, "%s\n", tree_code_name[(int) TREE_CODE (TREE_VALUE (arg))]); + fprintf(f, "arg value type code is: "); + fprintf(f, "%s\n", + tree_code_name[(int) TREE_CODE (TREE_TYPE (TREE_VALUE (arg)))]); + fprintf(f, "arg value type type code is:"); + fprintf(f, "%s\n", + tree_code_name[(int) TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))))]); + fprintf(f, "arg value is invariant: "); + if ( TREE_INVARIANT (TREE_VALUE (arg))) + fprintf(f, "yes\n"); + else + fprintf(f, "no\n"); + if (TREE_CODE ( TREE_VALUE (arg)) == ADDR_EXPR) + { + arg_0 = TREE_OPERAND (TREE_VALUE (arg), 0); + fprintf(f, "code of arg 0 of arg is: "); + fprintf(f, "%s\n", tree_code_name[(int) TREE_CODE (arg_0)]); + if (TREE_CODE (arg_0) == VAR_DECL) + { + if (DECL_NAME (arg_0)) + fprintf(f, + "arg 0 of arg is var_decl and its name is: %s\n", + IDENTIFIER_POINTER (DECL_NAME (arg_0))); + if (DECL_CONTEXT (arg_0)) + { + fprintf(f, "context of arg 0 of arg is: %s\n", + tree_code_name[(int)TREE_CODE (DECL_CONTEXT (arg_0))]); + fprintf(f, "context function name of arg 0 of arg is: %s\n", + IDENTIFIER_POINTER (DECL_NAME (DECL_CONTEXT (arg_0)))); + } + } + fprintf(f, "the type of arg 0 of arg is: %s\n", + tree_code_name[(int) TREE_CODE (TREE_TYPE (arg_0))]); + } + } + + /* Prints parameters trees of callsites. */ + static void + ipaa_callsite_param_trees_print (FILE *f) + { + ipa_method node; + ipa_callsite cs; + tree callTree, arg; + + fprintf(f, "\nCALLSITE PARAM TREES PRINT\n"); + for (node = cgraph_nodes; node; node = node->next) + { + for (cs = node->callees; cs; cs = cs->next_callee) + { + fprintf (f, "callsite %s ", cgraph_node_name (node)); + fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee)); + callTree = ipa_callsite_tree (cs); + if (TREE_CODE(callTree) != CALL_EXPR) + abort(); + arg = TREE_OPERAND (callTree, 1); + for (; arg != NULL_TREE; arg = TREE_CHAIN (arg)) + { + tree array_decl = NULL; + fprintf(f, "\n"); + if (ipaa_is_address_of_local_array (arg, &array_decl, + DECL_NAME (node->decl))) + ipaa_callsite_addr_local_array_print (f, arg); + } + } + } + } + + static void + ipaa_callsites_init_aliasing (ipa_method node) + { + ipaa_varslist_p list = ipaa_varslist_init (); + tree callTree; + ipa_callsite cs; + + for (cs = node->callees; cs; cs = cs->next_callee) + { + tree arg; + + callTree = ipa_callsite_tree (cs); + if (TREE_CODE(callTree) != CALL_EXPR) + abort(); + arg = TREE_OPERAND (callTree, 1); + for (; arg != NULL_TREE; arg = TREE_CHAIN (arg)) + { + tree array_decl = NULL; + if (ipaa_is_address_of_local_array (arg, &array_decl, + DECL_NAME (node->decl))) + list = ipaa_add_var (list, array_decl, callTree); + } + } + + if (dump_file) + { + fprintf (dump_file, + "\nVarslist of the function %s before computing modify:\n", + cgraph_node_name (node)); + ipaa_print_varslist (dump_file, list); + } + ipaa_method_compute_modify (node, list); + if (dump_file) + { + fprintf (dump_file, + "\nVarslist of the function %s after computing modify:\n", + cgraph_node_name (node)); + ipaa_print_varslist (dump_file, list); + } + + for (cs = node->callees; cs; cs = cs->next_callee) + { + tree arg1, arg2; + int i, j; + + /* This "if" handles the case with variable + number of parameters. The count of such callsites is zeroed + by ipa_init_stage function. */ + if (ipa_callsite_param_count (cs) == 0) + continue; + + callTree = ipa_callsite_tree (cs); + if (TREE_CODE(callTree) != CALL_EXPR) + abort(); + arg1 = TREE_OPERAND (callTree, 1); + for (i = 0; arg1 != NULL_TREE; arg1 = TREE_CHAIN (arg1), i++) + { + for (j = i + 1, arg2 = TREE_CHAIN (arg1); arg2 != NULL_TREE; + arg2 = TREE_CHAIN (arg2), j++) + { + tree array_decl1 = NULL; + tree array_decl2 = NULL; + + bool arg1_is_non_mod_address_of_local_array = + ipaa_is_address_of_local_array (arg1, &array_decl1, + DECL_NAME (node->decl)) && + !ipaa_varslist_is_modified (array_decl1, list); + bool arg2_is_non_mod_address_of_local_array = + ipaa_is_address_of_local_array (arg2, &array_decl2, + DECL_NAME (node->decl)) && + !ipaa_varslist_is_modified (array_decl2, list); + bool arg1_is_non_mod_formal = ipaa_is_non_modified_formal (cs, i, node); + bool arg2_is_non_mod_formal = ipaa_is_non_modified_formal (cs, j, node); + + /* arg1 and arg2 are local arrays. */ + if (arg1_is_non_mod_address_of_local_array && + arg2_is_non_mod_address_of_local_array) + { + if (array_decl1 == array_decl2) + /* they are aliased. */ + ipaa_callsite_set_pair_alias_info (cs, MUST_ALIAS, i, j); + else + /* they are not aliased. */ + ipaa_callsite_set_pair_alias_info (cs, NON_ALIAS, i, j); + } + else if ((arg1_is_non_mod_formal && + arg2_is_non_mod_address_of_local_array) || + (arg2_is_non_mod_formal && + arg1_is_non_mod_address_of_local_array)) + { + ipaa_callsite_set_pair_alias_info (cs, NON_ALIAS, i, j); + } + } + } + } + + ipaa_destroy_varslist (list); + } + + /* The modify computation driver. */ + static void + ipaa_method_compute_modify (ipa_method mt, ipaa_varslist_p list) + { + tree decl; + tree body; + basic_block bb; + struct function *func; + block_stmt_iterator bsi; + tree stmt; + ipaa_varslist_p p = list; + struct walk_tree_data wt_data; + + wt_data.list = list; + wt_data.stmt = NULL; + + decl = mt->decl; + /* this "if" is legacy from ipcp. */ + /* ??? Handle pending sizes case. Set all vars + in list to be modified. */ + if (DECL_UNINLINABLE (decl)) + { + while (ipaa_varslist_not_empty (p)) + { + ipaa_varslist_modified_set (p, true); + p = ipaa_varslist_next_var (p); + } + return; + } + body = DECL_SAVED_TREE (decl); + if (body !=NULL) + { + func = DECL_STRUCT_FUNCTION (decl); + FOR_EACH_BB_FN (bb, func) + { + for (bsi = bsi_start (bb); ! bsi_end_p (bsi); bsi_next (&bsi)) + { + stmt = bsi_stmt (bsi); + wt_data.stmt = stmt; + ipaa_modify_walk_tree_1 (&stmt, (void *)&wt_data); + } + } + } + } + + /* Walks tp to find whether vars from list are modified in + method mt (mt, list are parts of data). */ + static void + ipaa_modify_walk_tree_1 (tree *tp, void *data) + { + walk_tree (tp, ipaa_modify_walk_tree, data, NULL); + } + + /* Called by walk_tree. In the case a parameter + is modified within the method,the appropriate entry is + updated in the ipa_mod array. */ + static tree + ipaa_modify_walk_tree (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, + void *data) + { + tree t = *tp; + + struct walk_tree_data wt_data = *((walk_tree_data_p) data); + ipaa_varslist_p list = wt_data.list; + tree stmt = wt_data.stmt; + + switch (TREE_CODE (t)) + { + case MODIFY_EXPR: + if (TREE_CODE(TREE_OPERAND (t, 0)) == VAR_DECL) + { + tree var_decl = TREE_OPERAND (t, 0); + ipaa_varslist_p p = list; + while (p) + { + p = ipaa_varslist_find_var (var_decl, p); + if (p) + { + if (ipaa_varslist_call_expr (p) != stmt) + ipaa_varslist_modified_set (p, true); + p = ipaa_varslist_next_var (p); + } + } + } + break; + case ADDR_EXPR: + /* If the parameter's address is taken, + it could be modified. */ + + if( TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL ) + { + tree var_decl = TREE_OPERAND (t, 0); + ipaa_varslist_p p = list; + while (p) + { + p = ipaa_varslist_find_var (var_decl, p); + if (p) + { + if (ipaa_varslist_call_expr (p) != stmt) + ipaa_varslist_modified_set (p, true); + p = ipaa_varslist_next_var (p); + } + } + } + break; + case ASM_EXPR: + /* Asm code could modify any of the vars. */ + { + ipaa_varslist_p p = list; + while (p) + { + ipaa_varslist_modified_set (p, true); + p = ipaa_varslist_next_var (p); + } + } + break; + default: + break; + } + return NULL; + } + + /* Meet function for aliasing info. */ + static void + ipaa_meet_alias_info (ipaa_alias_info alias1, ipaa_alias_info alias2, + ipaa_alias_info* res_alias_p) + { + gcc_assert (res_alias_p != NULL); + + if (alias1 == alias2) + *res_alias_p = alias1; + else if (alias1 == MAY_ALIAS || alias2 == MAY_ALIAS) + *res_alias_p = MAY_ALIAS; + else if ((alias1 == DO_NOT_KNOW && alias2 == NON_ALIAS) || + (alias2 == DO_NOT_KNOW && alias1 == NON_ALIAS)) + *res_alias_p = NON_ALIAS; + else if ((alias1 == DO_NOT_KNOW && alias2 == MUST_ALIAS) || + (alias2 == DO_NOT_KNOW && alias1 == MUST_ALIAS)) + *res_alias_p = MUST_ALIAS; + else if ((alias1 == MUST_ALIAS && alias2 == NON_ALIAS) || + (alias2 == MUST_ALIAS && alias1 == NON_ALIAS)) + *res_alias_p = MAY_ALIAS; + + return; + } + + /* Interprocedural aliasing analysis. + The algorithm propagates aliasing info from the pairs of + caller's parameters to the pairs of callee's arguments. */ + static void + ipaa_propagate_stage (void) + { + int i, j, i1, j1; + ipa_methodlist_p wl; + ipa_method mt, callee; + ipa_callsite cs; + int count; + struct ipa_jump_func *jump_func1, *jump_func2; + ipaa_alias_info meet_res_alias_info; + ipaa_alias_info callsite_alias_info; + ipaa_alias_info method_alias_info; + ipa_method node; + enum Jfunc_type type1, type2; + union info *info_type1, *info_type2; + + wl = ipa_methodlist_init (); + for (node = cgraph_nodes; node; node = node->next) + { + for (cs = node->callees; cs; cs = cs->next_callee) + { + callee = ipa_callsite_callee (cs); + /* This "if" support functions with variable number of parameters. */ + if (!ipa_method_formal_count (callee)) + continue; + count = ipa_callsite_param_count (cs); + for (i = 0; i < count - 1; i++) + { + for (j = i + 1; j < count; j++) + { + callsite_alias_info = + ipaa_callsite_get_pair_alias_info (cs, i, j); + + method_alias_info = + ipaa_method_get_pair_alias_info (callee, i, j); + + ipaa_meet_alias_info (callsite_alias_info, method_alias_info, + &meet_res_alias_info); + if (meet_res_alias_info != method_alias_info) + { + ipaa_method_set_pair_alias_info (callee, + meet_res_alias_info, i, j); + ipa_add_method (&wl, callee); + } + } + } + } + } + + while (ipa_methodlist_not_empty (wl)) + { + mt = ipa_remove_method (&wl); + /* This "if" support functions with variable number of parameters. */ + if (!ipa_method_formal_count (mt)) + continue; + for (cs = mt->callees; cs; cs = cs->next_callee) + { + callee = ipa_callsite_callee (cs); + /* This "if" support functions with variable number of parameters. */ + if (!ipa_method_formal_count (callee)) + continue; + count = ipa_callsite_param_count (cs); + for (i = 0; i < count - 1; i++) + { + for (j = i + 1; j < count; j++) + { + jump_func1 = ipa_callsite_param (cs, i); + type1 = get_type (jump_func1); + info_type1 = ipa_jf_get_info_type (jump_func1); + + jump_func2 = ipa_callsite_param (cs, j); + type2 = get_type (jump_func2); + info_type2 = ipa_jf_get_info_type (jump_func2); + + if (type1 == FORMAL_IPATYPE && type2 == FORMAL_IPATYPE) + { + i1 = info_type1->formal_id; + j1 = info_type2->formal_id; + + if (i1 < j1) + callsite_alias_info = ipaa_method_get_pair_alias_info (mt, i1, j1); + else if (i1 == j1) + callsite_alias_info = MUST_ALIAS; + else + callsite_alias_info = ipaa_method_get_pair_alias_info (mt, j1, i1); + + method_alias_info = + ipaa_method_get_pair_alias_info (callee, i, j); + + ipaa_meet_alias_info (callsite_alias_info, method_alias_info, + &meet_res_alias_info); + if (meet_res_alias_info != method_alias_info) + { + ipaa_method_set_pair_alias_info (callee, + meet_res_alias_info, i, j); + ipa_add_method (&wl, callee); + } + } + } + } + } + } + } + + /* The IPA driver. */ + static void + ipa_driver (enum ipa_analysis_type type) + { + ipa_nodes_create (); + ipa_edges_create (); + if (dump_file) + { + if (type&IPA_CONSTANT_PROP) + fprintf (dump_file, "\nIPA constant propagation start:\n"); + if (type&IPA_ALIAS_ANALYSIS) + fprintf (dump_file, "\nIPA alias analysis start:\n"); + } + /* 1. Call the init stage to initialize + the ipa_node and ipa_edge structures. */ + ipa_init_stage (type); + if (dump_file) + { + fprintf (dump_file, "\nIPA structures before propagation:\n"); + if (type&IPA_CONSTANT_PROP) + ipcp_structures_print (dump_file); + if (type&IPA_ALIAS_ANALYSIS) + ipaa_structures_print (dump_file); + } + /* 2. Do the interprocedural propagation. */ + if (type&IPA_CONSTANT_PROP) + ipcp_iterate_stage (); + if (type&IPA_ALIAS_ANALYSIS) + ipaa_propagate_stage (); + if (dump_file) + { + fprintf (dump_file, "\nIPA structures after propagation:\n"); + if (type&IPA_CONSTANT_PROP) + ipcp_structures_print (dump_file); + if (type&IPA_ALIAS_ANALYSIS) + ipaa_structures_print (dump_file); + } + /* 3. Insert the constants found to the functions. */ + if (type&IPA_CONSTANT_PROP) + ipcp_insert_stage (); + if (type&IPA_ALIAS_ANALYSIS) + ipaa_insert_stage (); + /* Free all IPA structures. */ + ipa_free (); + ipa_nodes_free (); + ipa_edges_free (); + if (dump_file) + { + if (type&IPA_CONSTANT_PROP) + fprintf (dump_file, "\nIPA constant propagation end:\n"); + if (type&IPA_ALIAS_ANALYSIS) + fprintf (dump_file, "\nIPA alias analysis end:\n"); + } + /* 4. Clean up stage. */ + if(type&IPA_CONSTANT_PROP) + cgraph_remove_unreachable_nodes (true, NULL); + } + + /* This function saves aliasing info of formals calculated + at stage 2 for further compiler passes. */ + static void + ipaa_insert_stage (void) + { + /* TBD */ + } + + void + ipcp_driver (void) + { + ipa_driver (IPA_CONSTANT_PROP); + } + + void + ipaa_driver (void) + { + ipa_driver (IPA_ALIAS_ANALYSIS); + } + + static bool + cgraph_gate_alias (void) + { + return flag_ipa_alias; + } + + struct tree_opt_pass pass_ipa_alias = + { + "alias", /* name */ + cgraph_gate_alias, /* gate */ + NULL, /* function analysis */ + NULL, /* variable analysis */ + ipaa_driver, /* execute */ + NULL, /* function modification */ + NULL, /* variable modification */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_IPA_ALIAS_ANALYSIS, /* tv_id */ + 0, /* properties_required */ + PROP_trees, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_cgraph | TODO_dump_func, /* todo_flags_finish */ + 0 /* letter */ + }; Index: ipa_prop.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/Attic/ipa_prop.h,v retrieving revision 1.1.2.2 diff -c -3 -p -r1.1.2.2 ipa_prop.h *** ipa_prop.h 10 Feb 2005 23:26:49 -0000 1.1.2.2 --- ipa_prop.h 29 Apr 2005 15:21:22 -0000 *************** Software Foundation, 59 Temple Place - S *** 25,31 **** #include "tree.h" #include "real.h" /* The following definitions are used by ! IPA Constant Propagation algorithm. */ typedef struct tree_int_cst_lowhi ipcp_int; enum Jfunc_type { UNKNOWN_IPATYPE, --- 25,31 ---- #include "tree.h" #include "real.h" /* The following definitions are used by ! IPA analysis: Constant Propagation and Alias Analysis. */ typedef struct tree_int_cst_lowhi ipcp_int; enum Jfunc_type { UNKNOWN_IPATYPE, *************** enum Cvalue_type { *** 43,54 **** CONST_VALUE_FLOAT_REF, TOP }; union info{ ipcp_int int_value; unsigned int formal_id; REAL_VALUE_TYPE float_value; }; ! struct ipcp_jump_func { enum Jfunc_type type; union info info_type; --- 43,64 ---- CONST_VALUE_FLOAT_REF, TOP }; + enum alias_info { + DO_NOT_KNOW, /* top */ + MUST_ALIAS, + NON_ALIAS, + MAY_ALIAS /* bottom */ + }; + + typedef enum alias_info ipaa_alias_info; + + union info{ ipcp_int int_value; unsigned int formal_id; REAL_VALUE_TYPE float_value; }; ! struct ipa_jump_func { enum Jfunc_type type; union info info_type; *************** struct ipcp_formal *** 58,68 **** enum Cvalue_type cvalue_type; union info cvalue; }; ! struct ipcp_tree_map { tree param_tree; }; ! struct ipcp_modify { bool mod; }; --- 68,78 ---- enum Cvalue_type cvalue_type; union info cvalue; }; ! struct ipa_tree_map { tree param_tree; }; ! struct ipa_modify { bool mod; }; *************** struct ipa_node *** 78,90 **** /* Number of formal parameters of this method. When set to 0, this method's parameters would not be analyzed by the different stages of IPA CP. */ ! int ipcp_arg_num; /* Array of cvals. */ struct ipcp_formal* GTY ((skip (""))) ipcp_cval; /* Mapping each parameter to its PARM_DECL tree. */ ! struct ipcp_tree_map* GTY ((skip (""))) ipcp_param_tree; /* Indicating which parameter is modified in its method. */ ! struct ipcp_modify* GTY ((skip (""))) ipcp_mod; /* Only for cloned nodes this field would not be NULL, it points to the node that IPA cp cloned from. */ struct cgraph_node *ipcp_orig_node; --- 88,105 ---- /* Number of formal parameters of this method. When set to 0, this method's parameters would not be analyzed by the different stages of IPA CP. */ ! int ipa_arg_num; ! /* Number of pairs of formal parameters. */ ! int ipaa_num_pairs_args; /* Array of cvals. */ struct ipcp_formal* GTY ((skip (""))) ipcp_cval; /* Mapping each parameter to its PARM_DECL tree. */ ! struct ipa_tree_map* GTY ((skip (""))) ipa_param_tree; /* Indicating which parameter is modified in its method. */ ! struct ipa_modify* GTY ((skip (""))) ipa_mod; ! /* This array contains number of combinations between ! pairs of formals of the function. */ ! ipaa_alias_info* GTY ((skip (""))) ipaa_aliasing; /* Only for cloned nodes this field would not be NULL, it points to the node that IPA cp cloned from. */ struct cgraph_node *ipcp_orig_node; *************** struct ipa_edge *** 95,104 **** /* 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 ipcp_param_num; /* Array of the callsite's jump function of each parameter. */ ! struct ipcp_jump_func* GTY ((skip (""))) ipcp_param_map; }; void ipcp_driver (void); #endif /* IPA_PROP_H */ --- 110,130 ---- /* 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; ! /* Number of pairs of actual parameters. */ ! int ipaa_num_pairs_args; /* Array of the callsite's jump function of each parameter. */ ! struct ipa_jump_func* GTY ((skip (""))) ipa_param_map; ! /* This array contains number of combinations between ! pairs of formals of the callsite function. */ ! ipaa_alias_info* GTY ((skip (""))) ipaa_aliasing; ! }; ! enum ipa_analysis_type { ! IPA_CONSTANT_PROP = 0x1, ! IPA_ALIAS_ANALYSIS = 0x2 }; + void ipcp_driver (void); + void ipaa_driver (void); #endif /* IPA_PROP_H */ Index: timevar.def =================================================================== RCS file: /cvs/gcc/gcc/gcc/timevar.def,v retrieving revision 1.14.2.35.2.15 diff -c -3 -p -r1.14.2.35.2.15 timevar.def *** timevar.def 15 Apr 2005 13:27:25 -0000 1.14.2.35.2.15 --- timevar.def 29 Apr 2005 15:21:22 -0000 *************** DEFTIMEVAR (TV_IPA_OPT , " *** 45,50 **** --- 45,51 ---- DEFTIMEVAR (TV_IPA_ANALYSIS , "ipa analysis") DEFTIMEVAR (TV_IPA_CONSTANT_PROP , "ipa cp") DEFTIMEVAR (TV_IPA_STATIC_VAR , "ipa static vars") + DEFTIMEVAR (TV_IPA_ALIAS_ANALYSIS , "ipa alias analysis") /* Time spent by constructing CFG. */ DEFTIMEVAR (TV_CFG , "cfg construction") /* Time spent by cleaning up CFG. */ Index: tree-optimize.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v retrieving revision 1.1.4.122.2.43 diff -c -3 -p -r1.1.4.122.2.43 tree-optimize.c *** tree-optimize.c 25 Apr 2005 08:53:27 -0000 1.1.4.122.2.43 --- tree-optimize.c 29 Apr 2005 15:21:22 -0000 *************** init_tree_optimization_passes (void) *** 482,487 **** --- 482,488 ---- /* Intraprocedural optimization passes. */ p = &all_ipa_passes; + NEXT_PASS (pass_ipa_alias); NEXT_PASS (pass_ipa_cp); NEXT_PASS (pass_ipa_inline); NEXT_PASS (pass_ipa_static); Index: tree-pass.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-pass.h,v retrieving revision 1.1.2.12.2.22 diff -c -3 -p -r1.1.2.12.2.22 tree-pass.h *** tree-pass.h 15 Apr 2005 13:27:42 -0000 1.1.2.12.2.22 --- tree-pass.h 29 Apr 2005 15:21:22 -0000 *************** extern struct tree_opt_pass pass_vrp; *** 245,250 **** --- 245,251 ---- extern struct tree_opt_pass pass_create_structure_vars; extern struct tree_opt_pass pass_promote_statics; + extern struct tree_opt_pass pass_ipa_alias; extern struct tree_opt_pass pass_ipa_cp; extern struct tree_opt_pass pass_ipa_inline; extern struct tree_opt_pass pass_ipa_static;