aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog55
-rw-r--r--gcc/Makefile.in18
-rw-r--r--gcc/cgraph.h2
-rw-r--r--gcc/cgraphunit.c132
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/integrate.c76
-rw-r--r--gcc/passes.c1
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);