diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 55 | ||||
-rw-r--r-- | gcc/Makefile.in | 18 | ||||
-rw-r--r-- | gcc/cgraph.h | 2 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 132 | ||||
-rw-r--r-- | gcc/common.opt | 4 | ||||
-rw-r--r-- | gcc/integrate.c | 76 | ||||
-rw-r--r-- | gcc/passes.c | 1 |
7 files changed, 208 insertions, 80 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bc0f293..1f090f4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,58 @@ +2005-08-01 Razya Ladelsky <razya@il.ibm.com> + + * cgraph.h (update_call_expr, cgraph_copy_node_for_versioning, + cgraph_function_versioning): New declarations. + * cgraphunit.c: Add include to ipa-prop.h. + (update_call_expr, cgraph_copy_node_for_versioning, + cgraph_function_versioning): New functions. + * integrate.c (copy_decl_for_inlining): Remove. + * ipa-prop.h (ipa_replace_map): New struct. + (struct ipa_node): Add ipcp_orig_node, count_scale, new fields. + * ipa-cp.c (ipcp_method_orig_node, ipcp_method_is_cloned, + ipcp_method_set_orig_node, ipcp_cloned_create, ipcp_method_get_scale, + ipcp_method_set_scale, ipcp_method_compute_scale, ipcp_after_propagate, + ipcp_iterate_stage, ipcp_method_scale_print, + ipcp_profile_mt_count_print, ipcp_profile_cs_count_print, + ipcp_profile_edge_print, ipcp_profile_bb_print , ipcp_profile_print, + ipcp_replace_map_create, ipcp_redirect, ipcp_update_callgraph, + ipcp_update_bb_counts, ipcp_update_profiling, + ipcp_update_edges_counts): New functions. + (ipcp_method_cval_init): Remove restriction regarding local methods. + (ipcp_init_stage): Add ipcp_method_compute_scale. + (ipcp_insert_stage): Add versioning. + (ipcp_structures_print): Add ipcp_method_scale_print. + (ipcp_driver): Dump profiling info. + * Makefile.in: Remove integrate.h dependency from tree-inline.o. + Add ipa-prop.h dependency to tree-inline.o and cgraphunit.o. + * tree-inline.c: Remove include to integrate.h, Add include ipa-prop.h. + (struct inline_data): Add versioning_p, ipa_info, new fields. + (remap_decl, mark_local_for_remap_r, setup_one_parameter, + declare_return_variable): Replace calls to copy_decl_for_inlining with + copy_decl_for_dup. + (copy_body_r, copy_bb, copy_cfg_body, copy_tree_r, inlining_p): Add + versioning support. + (copy_decl_for_dup): Rename from copy_decl_for_inlining. + Add argument VERSIONING. + (copy_arguments_for_versioning, copy_static_chain, + function_versionable_p, tree_versionable_function_p, + tree_function_versioning, replace_ref_tree): New functions. + * tree-inline.h: Include varray.h. + (tree_versionable_function_p, tree_function_versioning, + tree copy_decl_for_dup): New declarations. + +2005-08-01 Razya Ladelsky <razya@il.ibm.com> + + * ipa-cp.c: New file. Contains IPCP specific functionality. + * ipa-prop.h: New file. Contains structures/definitions that can be + used by several interprocedural data flow optimizations (and also IPCP). + * ipa-prop.c: New file. + * Makefile.in: Add ipa-cp.c, ipa-prop.h, ipa-prop.c. + * common.opt: Add ipa-cp flag. + * timevar.def: Add IPCP optimization. + * tree-optimize.c (init_tree_optimization_passes): Schedule + pass_ipa_cp. + * tree-pass.h (pass_ipa_cp): Declare. + 2005-08-01 Kazu Hirata <kazu@codesourcery.com> * dwarf2out.c, fold-const.c, ipa-type-escape.c, diff --git a/gcc/Makefile.in b/gcc/Makefile.in index e465e00..c802330 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -975,7 +975,8 @@ OBJS-common = \ OBJS-md = $(out_object_file) OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) tree-inline.o \ cgraph.o cgraphunit.o tree-nomudflap.o ipa.o ipa-inline.o \ - ipa-utils.o ipa-reference.o ipa-pure-const.o ipa-type-escape.o + ipa-utils.o ipa-reference.o ipa-pure-const.o ipa-type-escape.o \ + ipa-prop.o ipa-cp.o OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive) @@ -1715,9 +1716,10 @@ tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ tree-iterator.h tree-pass.h $(DIAGNOSTIC_H) tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(RTL_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h insn-config.h \ - $(INTEGRATE_H) $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \ + $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \ langhooks.h tree-inline.h $(CGRAPH_H) intl.h function.h $(TREE_GIMPLE_H) \ - debug.h $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-iterator.h tree-mudflap.h + debug.h $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-iterator.h tree-mudflap.h \ + ipa-prop.h print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(GGC_H) langhooks.h real.h tree-iterator.h stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ @@ -2151,8 +2153,15 @@ cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h tree-inline.h toplev.h $(FLAGS_H) $(GGC_H) \ $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h function.h $(TREE_GIMPLE_H) \ $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \ - $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) + $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) +ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ + langhooks.h $(GGC_H) target.h $(CGRAPH_H) ipa-prop.h \ + tree-flow.h $(TM_H) tree-pass.h $(FLAGS_H) $(TREE_H) +ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ + langhooks.h target.h $(CGRAPH_H) ipa-prop.h \ + tree-flow.h $(TM_H) tree-pass.h $(FLAGS_H) $(TREE_H) \ + diagnostic.h ipa-inline.o : ipa-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h tree-inline.h $(FLAGS_H) $(CGRAPH_H) intl.h \ $(DIAGNOSTIC_H) $(FIBHEAP_H) $(PARAMS_H) $(TIMEVAR_H) tree-pass.h \ @@ -2712,6 +2721,7 @@ GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/cgraph.h \ $(srcdir)/c-common.h $(srcdir)/c-tree.h $(srcdir)/reload.h \ $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \ + $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c\ $(srcdir)/dbxout.c $(srcdir)/dwarf2out.c $(srcdir)/dwarf2asm.c \ $(srcdir)/dojump.c $(srcdir)/tree-profile.c \ $(srcdir)/emit-rtl.c $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \ diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 81eb10b..ccb2cdd 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -281,6 +281,8 @@ void cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate); void cgraph_build_static_cdtor (char which, tree body, int priority); void cgraph_reset_static_var_maps (void); void init_cgraph (void); +struct cgraph_node *cgraph_function_versioning (struct cgraph_node *, + varray_type, varray_type); /* In ipa.c */ bool cgraph_remove_unreachable_nodes (bool, FILE *); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index f8f864c..a10859d 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -162,6 +162,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "c-common.h" #include "intl.h" #include "function.h" +#include "ipa-prop.h" #include "tree-gimple.h" #include "tree-pass.h" #include "output.h" @@ -1368,3 +1369,134 @@ init_cgraph (void) { cgraph_dump_file = dump_begin (TDI_cgraph, NULL); } + +/* The edges representing the callers of the NEW_VERSION node were + fixed by cgraph_function_versioning (), now the call_expr in their + respective tree code should be updated to call the NEW_VERSION. */ + +static void +update_call_expr (struct cgraph_node *new_version) +{ + struct cgraph_edge *e; + + gcc_assert (new_version); + for (e = new_version->callers; e; e = e->next_caller) + /* Update the call expr on the edges + to call the new version. */ + TREE_OPERAND (TREE_OPERAND (get_call_expr_in (e->call_stmt), 0), 0) = new_version->decl; +} + + +/* Create a new cgraph node which is the new version of + OLD_VERSION node. REDIRECT_CALLERS holds the callers + edges which should be redirected to point to + NEW_VERSION. ALL the callees edges of OLD_VERSION + are cloned to the new version node. Return the new + version node. */ + +static struct cgraph_node * +cgraph_copy_node_for_versioning (struct cgraph_node *old_version, + tree new_decl, varray_type redirect_callers) + { + struct cgraph_node *new_version; + struct cgraph_edge *e, *new_e; + struct cgraph_edge *next_callee; + unsigned i; + + gcc_assert (old_version); + + new_version = cgraph_node (new_decl); + + new_version->analyzed = true; + new_version->local = old_version->local; + new_version->global = old_version->global; + new_version->rtl = new_version->rtl; + new_version->reachable = true; + new_version->count = old_version->count; + + /* Clone the old node callees. Recursive calls are + also cloned. */ + for (e = old_version->callees;e; e=e->next_callee) + { + new_e = cgraph_clone_edge (e, new_version, e->call_stmt, 0, e->loop_nest, true); + new_e->count = e->count; + } + /* Fix recursive calls. + If OLD_VERSION has a recursive call after the + previous edge cloning, the new version will have an edge + pointing to the old version, which is wrong; + Redirect it to point to the new version. */ + for (e = new_version->callees ; e; e = next_callee) + { + next_callee = e->next_callee; + if (e->callee == old_version) + cgraph_redirect_edge_callee (e, new_version); + + if (!next_callee) + break; + } + if (redirect_callers) + for (i = 0; i < VARRAY_ACTIVE_SIZE (redirect_callers); i++) + { + e = VARRAY_GENERIC_PTR (redirect_callers, i); + /* Redirect calls to the old version node + to point to it's new version. */ + cgraph_redirect_edge_callee (e, new_version); + } + + return new_version; + } + + /* Perform function versioning. + Function versioning includes copying of the tree and + a callgraph update (creating a new cgraph node and updating + its callees and callers). + + REDIRECT_CALLERS varray includes the edges to be redirected + to the new version. + + TREE_MAP is a mapping of tree nodes we want to replace with + new ones (according to results of prior analysis). + OLD_VERSION_NODE is the node that is versioned. + It returns the new version's cgraph node. */ + +struct cgraph_node * +cgraph_function_versioning (struct cgraph_node *old_version_node, + varray_type redirect_callers, + varray_type tree_map) +{ + tree old_decl = old_version_node->decl; + struct cgraph_node *new_version_node = NULL; + tree new_decl; + + if (!tree_versionable_function_p (old_decl)) + return NULL; + + /* Make a new FUNCTION_DECL tree node for the + new version. */ + new_decl = copy_node (old_decl); + + /* Create the new version's call-graph node. + and update the edges of the new node. */ + new_version_node = + cgraph_copy_node_for_versioning (old_version_node, new_decl, + redirect_callers); + + /* Copy the OLD_VERSION_NODE function tree to the new version. */ + tree_function_versioning (old_decl, new_decl, tree_map); + /* Update the call_expr on the edges to call the new version node. */ + update_call_expr (new_version_node); + + /* Update the new version's properties. + Make The new version visible only within this translation unit. + ??? We cannot use COMDAT linkage because there is no + ABI support for this. */ + DECL_EXTERNAL (new_version_node->decl) = 0; + DECL_ONE_ONLY (new_version_node->decl) = 0; + TREE_PUBLIC (new_version_node->decl) = 0; + DECL_COMDAT (new_version_node->decl) = 0; + new_version_node->local.externally_visible = 0; + new_version_node->local.local = 1; + new_version_node->lowered = true; + return new_version_node; +} diff --git a/gcc/common.opt b/gcc/common.opt index 28d9a06..a993ff9 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -507,6 +507,10 @@ fipa-type-escape Common Report Var(flag_ipa_type_escape) Init(0) Type based escape and alias analysis +fipa-cp +Common Report Var(flag_ipa_cp) +Perform Interprocedural constant propagation + fivopts Common Report Var(flag_ivopts) Init(1) Optimize induction variables on trees diff --git a/gcc/integrate.c b/gcc/integrate.c index eadf660..ee9c184 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -89,82 +89,6 @@ function_attribute_inlinable_p (tree fndecl) return true; } -/* Copy NODE (which must be a DECL). The DECL originally was in the FROM_FN, - but now it will be in the TO_FN. */ - -tree -copy_decl_for_inlining (tree decl, tree from_fn, tree to_fn) -{ - tree copy; - - /* Copy the declaration. */ - if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL) - { - tree type = TREE_TYPE (decl); - - /* For a parameter or result, we must make an equivalent VAR_DECL, not a - new PARM_DECL. */ - copy = build_decl (VAR_DECL, DECL_NAME (decl), type); - TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl); - TREE_READONLY (copy) = TREE_READONLY (decl); - TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl); - DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (decl); - } - else - { - copy = copy_node (decl); - /* The COPY is not abstract; it will be generated in TO_FN. */ - DECL_ABSTRACT (copy) = 0; - lang_hooks.dup_lang_specific_decl (copy); - - /* TREE_ADDRESSABLE isn't used to indicate that a label's - address has been taken; it's for internal bookkeeping in - expand_goto_internal. */ - if (TREE_CODE (copy) == LABEL_DECL) - { - TREE_ADDRESSABLE (copy) = 0; - LABEL_DECL_UID (copy) = -1; - } - } - - /* Don't generate debug information for the copy if we wouldn't have - generated it for the copy either. */ - DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl); - DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl); - - /* Set the DECL_ABSTRACT_ORIGIN so the debugging routines know what - declaration inspired this copy. */ - DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl); - - /* The new variable/label has no RTL, yet. */ - if (CODE_CONTAINS_STRUCT (TREE_CODE (copy), TS_DECL_WRTL) - && !TREE_STATIC (copy) && !DECL_EXTERNAL (copy)) - SET_DECL_RTL (copy, NULL_RTX); - - /* These args would always appear unused, if not for this. */ - TREE_USED (copy) = 1; - - /* Set the context for the new declaration. */ - if (!DECL_CONTEXT (decl)) - /* Globals stay global. */ - ; - else if (DECL_CONTEXT (decl) != from_fn) - /* Things that weren't in the scope of the function we're inlining - from aren't in the scope we're inlining to, either. */ - ; - else if (TREE_STATIC (decl)) - /* Function-scoped static variables should stay in the original - function. */ - ; - else - /* Ordinary automatic local variables are now in the scope of the - new function. */ - DECL_CONTEXT (copy) = to_fn; - - return copy; -} - - /* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so that it points to the node itself, thus indicating that the node is its diff --git a/gcc/passes.c b/gcc/passes.c index 16f816c..76f5da3 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -433,6 +433,7 @@ init_optimization_passes (void) p = &all_ipa_passes; NEXT_PASS (pass_early_ipa_inline); NEXT_PASS (pass_early_local_passes); + NEXT_PASS (pass_ipa_cp); NEXT_PASS (pass_ipa_inline); NEXT_PASS (pass_ipa_reference); NEXT_PASS (pass_ipa_pure_const); |