summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2008-09-18 17:28:40 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2008-09-18 17:28:40 +0000
commit86844d6c095dfa67c72e0dd4db3446aa85c5e663 (patch)
treeebbd388fee9c2b29fa34e1972bac913405e30d33 /gcc
parent9abaa85a3de5dd957de49a911fdcaab1122d2d7f (diff)
downloadgcc-86844d6c095dfa67c72e0dd4db3446aa85c5e663.tar.gz
PR middle-end/37448
* ipa-reference.c (ipa_reference_local_vars_info_d, ipa_reference_global_vars_info_d, ipa_reference_local_vars_info_t, ipa_reference_global_vars_info_t, ipa_reference_vars_info_t): Move here from ipa-reference.h (node_duplication_hook_holder, node_removal_hook_holder): New. (get_reference_vars_info_from_cgraph): Rename to ... (get_reference_vars_info): ... this one, use cgraph uids. (get_local_reference_vars_info, get_global_reference_vars_info): Use cgraph instead of decl. (ipa_reference_get_read_local, ipa_reference_get_written_local): Remove. (ipa_reference_get_read_global, ipa_reference_get_not_read_global ipa_reference_get_written_global, ipa_reference_get_not_written_global): Use cgraph argument. (check_call): Simplify avail check. (scan_stmt_for_static_refs): Update. (propagate_bits): Update. (merge_callee_local_info): Remove. (init_function_info): Use cgraph nodes. (clean_function_local_data): Break out from ... (clean_function): ... here. (copy_local_bitmap, copy_global_bitmap): New functions. (duplicate_node_data, remove_node_data): New functions. (generate_summary): Register hooks; use visibility instead of master clones. (propafate): Use cgraph nodes; copy bitmap to each node in cycle. * ipa-reference.h (ipa_reference_local_vars_info_d, ipa_reference_global_vars_info_d, ipa_reference_local_vars_info_t, ipa_reference_global_vars_info_t, ipa_reference_vars_info_t): Move to ipa-reference.c (ipa_reference_get_read_local, ipa_reference_get_written_local): Remove. (ipa_reference_get_read_global, ipa_reference_get_written_global, ipa_reference_get_not_read_global, ipa_reference_get_not_written_global): Update prototype. * ipa-pure-const.c (funct_state_vec): Turn into VECtor. (init_state): Remove. (node_duplication_hook_holder, node_removal_hook_holder): New. (get_function_state, set_function_state): Use VECtor. (analyze_function): Check body availability. (add_new_function): Likewise. (duplicate_node_data, remove_node_data): New. (generate_summary): Register hooks; do not care about clones. (propafate): Do not care about clones; recursive functions are not looping. * ipa-utils.c (searchc, ipa_utils_reduced_inorder): Do not skip clones. * ipa-prop.c (edge_removal_hook_holder, node_removal_hook_holder, * edge_duplication_hook_holder, node_duplication_hook_holder): Make static. * tree-flow.h (function_ann_d): Remove reference_vars_info. * tree-ssa-opreands.c (add_call_clobber_ops, add_call_read_ops): Update call of ipa-reference accesors. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@140463 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog54
-rw-r--r--gcc/ipa-prop.c8
-rw-r--r--gcc/ipa-pure-const.c82
-rw-r--r--gcc/ipa-reference.c404
-rw-r--r--gcc/ipa-reference.h57
-rw-r--r--gcc/ipa-utils.c50
-rw-r--r--gcc/tree-ssa-operands.c6
7 files changed, 361 insertions, 300 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 99b34c52c4e..0c49b73322f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,57 @@
+2008-09-18 Jan Hubicka <jh@suse.cz>
+
+ PR middle-end/37448
+ * ipa-reference.c (ipa_reference_local_vars_info_d,
+ ipa_reference_global_vars_info_d,
+ ipa_reference_local_vars_info_t, ipa_reference_global_vars_info_t,
+ ipa_reference_vars_info_t): Move here from ipa-reference.h
+ (node_duplication_hook_holder, node_removal_hook_holder): New.
+ (get_reference_vars_info_from_cgraph): Rename to ...
+ (get_reference_vars_info): ... this one, use cgraph uids.
+ (get_local_reference_vars_info, get_global_reference_vars_info):
+ Use cgraph instead of decl.
+ (ipa_reference_get_read_local, ipa_reference_get_written_local): Remove.
+ (ipa_reference_get_read_global, ipa_reference_get_not_read_global
+ ipa_reference_get_written_global, ipa_reference_get_not_written_global): Use
+ cgraph argument.
+ (check_call): Simplify avail check.
+ (scan_stmt_for_static_refs): Update.
+ (propagate_bits): Update.
+ (merge_callee_local_info): Remove.
+ (init_function_info): Use cgraph nodes.
+ (clean_function_local_data): Break out from ...
+ (clean_function): ... here.
+ (copy_local_bitmap, copy_global_bitmap): New functions.
+ (duplicate_node_data, remove_node_data): New functions.
+ (generate_summary): Register hooks; use visibility instead of
+ master clones.
+ (propafate): Use cgraph nodes; copy bitmap to each node in cycle.
+ * ipa-reference.h (ipa_reference_local_vars_info_d,
+ ipa_reference_global_vars_info_d,
+ ipa_reference_local_vars_info_t, ipa_reference_global_vars_info_t,
+ ipa_reference_vars_info_t): Move to ipa-reference.c
+ (ipa_reference_get_read_local, ipa_reference_get_written_local):
+ Remove.
+ (ipa_reference_get_read_global, ipa_reference_get_written_global,
+ ipa_reference_get_not_read_global, ipa_reference_get_not_written_global):
+ Update prototype.
+ * ipa-pure-const.c (funct_state_vec): Turn into VECtor.
+ (init_state): Remove.
+ (node_duplication_hook_holder, node_removal_hook_holder): New.
+ (get_function_state, set_function_state): Use VECtor.
+ (analyze_function): Check body availability.
+ (add_new_function): Likewise.
+ (duplicate_node_data, remove_node_data): New.
+ (generate_summary): Register hooks; do not care about clones.
+ (propafate): Do not care about clones; recursive functions are not looping.
+ * ipa-utils.c (searchc, ipa_utils_reduced_inorder): Do not skip clones.
+ * ipa-prop.c (edge_removal_hook_holder, node_removal_hook_holder,
+ * edge_duplication_hook_holder, node_duplication_hook_holder): Make
+ static.
+ * tree-flow.h (function_ann_d): Remove reference_vars_info.
+ * tree-ssa-opreands.c (add_call_clobber_ops, add_call_read_ops): Update call of
+ ipa-reference accesors.
+
2008-09-18 Simon Baldwin <simonb@google.com>
* c-opts.c (c_common_handle_option): Add handling for
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 90b0333e783..be1f96efa15 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -40,10 +40,10 @@ VEC (ipa_node_params_t, heap) *ipa_node_params_vector;
VEC (ipa_edge_args_t, heap) *ipa_edge_args_vector;
/* Holders of ipa cgraph hooks: */
-struct cgraph_edge_hook_list *edge_removal_hook_holder;
-struct cgraph_node_hook_list *node_removal_hook_holder;
-struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
-struct cgraph_2node_hook_list *node_duplication_hook_holder;
+static struct cgraph_edge_hook_list *edge_removal_hook_holder;
+static struct cgraph_node_hook_list *node_removal_hook_holder;
+static struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
+static struct cgraph_2node_hook_list *node_duplication_hook_holder;
/* Initialize worklist to contain all functions. */
struct ipa_func_list *
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 20abdf3f477..f21638f383e 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -94,19 +94,14 @@ typedef struct funct_state_d * funct_state;
/* Array, indexed by cgraph node uid, of function states. */
-static funct_state *funct_state_vec;
+DEF_VEC_P (funct_state);
+DEF_VEC_ALLOC_P (funct_state, heap);
+static VEC (funct_state, heap) *funct_state_vec;
/* Holders of ipa cgraph hooks: */
static struct cgraph_node_hook_list *function_insertion_hook_holder;
-
-/* Init the function state. */
-
-static void
-init_state (void)
-{
- funct_state_vec = XCNEWVEC (funct_state, cgraph_max_uid);
-}
-
+static struct cgraph_2node_hook_list *node_duplication_hook_holder;
+static struct cgraph_node_hook_list *node_removal_hook_holder;
/* Init the function state. */
@@ -122,7 +117,10 @@ finish_state (void)
static inline funct_state
get_function_state (struct cgraph_node *node)
{
- return funct_state_vec[node->uid];
+ if (!funct_state_vec
+ || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid)
+ return NULL;
+ return VEC_index (funct_state, funct_state_vec, node->uid);
}
/* Set the function state S for NODE. */
@@ -130,7 +128,10 @@ get_function_state (struct cgraph_node *node)
static inline void
set_function_state (struct cgraph_node *node, funct_state s)
{
- funct_state_vec[node->uid] = s;
+ if (!funct_state_vec
+ || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid)
+ VEC_safe_grow_cleared (funct_state, heap, funct_state_vec, node->uid + 1);
+ VEC_replace (funct_state, funct_state_vec, node->uid, s);
}
/* Check to see if the use (or definition when CHECKING_WRITE is true)
@@ -585,6 +586,9 @@ analyze_function (struct cgraph_node *fn)
tree decl = fn->decl;
funct_state l = XCNEW (struct funct_state_d);
+ if (cgraph_function_body_availability (fn) <= AVAIL_OVERWRITABLE)
+ return;
+
set_function_state (fn, l);
l->pure_const_state = IPA_CONST;
@@ -683,7 +687,8 @@ end:
static void
add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
- funct_state_vec = XRESIZEVEC (funct_state, funct_state_vec, cgraph_max_uid);
+ if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
+ return;
/* There are some shared nodes, in particular the initializers on
static declarations. We do not need to scan them more than once
since all we would be interested in are the addressof
@@ -694,6 +699,33 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
visited_nodes = NULL;
}
+/* Called when new clone is inserted to callgraph late. */
+
+static void
+duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
+ void *data ATTRIBUTE_UNUSED)
+{
+ if (get_function_state (src))
+ {
+ funct_state l = XNEW (struct funct_state_d);
+ gcc_assert (!get_function_state (dst));
+ memcpy (l, get_function_state (src), sizeof (*l));
+ set_function_state (dst, l);
+ }
+}
+
+/* Called when new clone is inserted to callgraph late. */
+
+static void
+remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+{
+ if (get_function_state (node))
+ {
+ free (get_function_state (node));
+ set_function_state (node, NULL);
+ }
+}
+
/* Analyze each function in the cgraph to see if it is locally PURE or
CONST. */
@@ -703,9 +735,12 @@ generate_summary (void)
{
struct cgraph_node *node;
+ node_removal_hook_holder =
+ cgraph_add_node_removal_hook (&remove_node_data, NULL);
+ node_duplication_hook_holder =
+ cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
function_insertion_hook_holder =
cgraph_add_function_insertion_hook (&add_new_function, NULL);
- init_state ();
/* There are some shared nodes, in particular the initializers on
static declarations. We do not need to scan them more than once
since all we would be interested in are the addressof
@@ -714,14 +749,12 @@ generate_summary (void)
/* Process all of the functions.
- We do not want to process any of the clones so we check that this
- is a master clone. However, we do NOT process any
- AVAIL_OVERWRITABLE functions (these are never clones) we cannot
+ We do NOT process any AVAIL_OVERWRITABLE functions, we cannot
guarantee that what we learn about the one we see will be true
for the one that overrides it.
*/
for (node = cgraph_nodes; node; node = node->next)
- if (node->analyzed && cgraph_is_master_clone (node))
+ if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
analyze_function (node);
pointer_set_destroy (visited_nodes);
@@ -745,6 +778,8 @@ propagate (void)
struct ipa_dfs_info * w_info;
cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
+ cgraph_remove_node_duplication_hook (node_duplication_hook_holder);
+ cgraph_remove_node_removal_hook (node_removal_hook_holder);
order_pos = ipa_utils_reduced_inorder (order, true, false);
if (dump_file)
{
@@ -788,12 +823,8 @@ propagate (void)
for (e = w->callees; e; e = e->next_callee)
{
struct cgraph_node *y = e->callee;
- /* Only look at the master nodes and skip external nodes. */
- y = cgraph_master_clone (y);
- if (w == y)
- looping = true;
- if (y)
+ if (cgraph_function_body_availability (y) > AVAIL_OVERWRITABLE)
{
funct_state y_l = get_function_state (y);
if (pure_const_state < y_l->pure_const_state)
@@ -861,11 +892,12 @@ propagate (void)
free (node->aux);
node->aux = NULL;
}
- if (node->analyzed && cgraph_is_master_clone (node))
+ if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
free (get_function_state (node));
}
free (order);
+ VEC_free (funct_state, heap, funct_state_vec);
finish_state ();
return 0;
}
@@ -873,7 +905,7 @@ propagate (void)
static bool
gate_pure_const (void)
{
- return (flag_ipa_pure_const
+ return (flag_ipa_pure_const
/* Don't bother doing anything if the program has errors. */
&& !(errorcount || sorrycount));
}
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index 6c76ccc8a4e..a9afd457a73 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -69,6 +69,52 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "langhooks.h"
+/* The static variables defined within the compilation unit that are
+ loaded or stored directly by function that owns this structure. */
+
+struct ipa_reference_local_vars_info_d
+{
+ bitmap statics_read;
+ bitmap statics_written;
+
+ /* Set when this function calls another function external to the
+ compilation unit or if the function has a asm clobber of memory.
+ In general, such calls are modeled as reading and writing all
+ variables (both bits on) but sometime there are attributes on the
+ called function so we can do better. */
+ bool calls_read_all;
+ bool calls_write_all;
+};
+
+/* Statics that are read and written by some set of functions. The
+ local ones are based on the loads and stores local to the function.
+ The global ones are based on the local info as well as the
+ transitive closure of the functions that are called. The
+ structures are separated to allow the global structures to be
+ shared between several functions since every function within a
+ strongly connected component will have the same information. This
+ sharing saves both time and space in the computation of the vectors
+ as well as their translation from decl_uid form to ann_uid
+ form. */
+
+struct ipa_reference_global_vars_info_d
+{
+ bitmap statics_read;
+ bitmap statics_written;
+ bitmap statics_not_read;
+ bitmap statics_not_written;
+};
+
+typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
+typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
+struct ipa_reference_vars_info_d
+{
+ ipa_reference_local_vars_info_t local;
+ ipa_reference_global_vars_info_t global;
+};
+
+typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
+
/* This splay tree contains all of the static variables that are
being considered by the compilation level alias analysis. For
module_at_a_time compilation, this is the set of static but not
@@ -101,6 +147,8 @@ static bitmap_obstack global_info_obstack;
/* Holders of ipa cgraph hooks: */
static struct cgraph_node_hook_list *function_insertion_hook_holder;
+static struct cgraph_2node_hook_list *node_duplication_hook_holder;
+static struct cgraph_node_hook_list *node_removal_hook_holder;
enum initialization_status_t
{
@@ -111,19 +159,37 @@ enum initialization_status_t
tree memory_identifier_string;
+/* Vector where the reference var infos are actually stored. */
+DEF_VEC_P (ipa_reference_vars_info_t);
+DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap);
+static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector;
+
/* Return the ipa_reference_vars structure starting from the cgraph NODE. */
static inline ipa_reference_vars_info_t
-get_reference_vars_info_from_cgraph (struct cgraph_node * node)
+get_reference_vars_info (struct cgraph_node *node)
+{
+ if (!ipa_reference_vars_vector
+ || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid)
+ return NULL;
+ return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid);
+}
+
+/* Return the ipa_reference_vars structure starting from the cgraph NODE. */
+static inline void
+set_reference_vars_info (struct cgraph_node *node, ipa_reference_vars_info_t info)
{
- return get_function_ann (node->decl)->reference_vars_info;
+ if (!ipa_reference_vars_vector
+ || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid)
+ VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector, node->uid + 1);
+ VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid, info);
}
/* Get a bitmap that contains all of the locally referenced static
variables for function FN. */
static ipa_reference_local_vars_info_t
-get_local_reference_vars_info (tree fn)
+get_local_reference_vars_info (struct cgraph_node *fn)
{
- ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info;
+ ipa_reference_vars_info_t info = get_reference_vars_info (fn);
if (info)
return info->local;
@@ -136,9 +202,9 @@ get_local_reference_vars_info (tree fn)
variables for function FN. */
static ipa_reference_global_vars_info_t
-get_global_reference_vars_info (tree fn)
+get_global_reference_vars_info (struct cgraph_node *fn)
{
- ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info;
+ ipa_reference_vars_info_t info = get_reference_vars_info (fn);
if (info)
return info->global;
@@ -148,39 +214,11 @@ get_global_reference_vars_info (tree fn)
}
/* Return a bitmap indexed by VAR_DECL uid for the static variables
- that may be read locally by the execution of the function fn.
- Returns NULL if no data is available. */
-
-bitmap
-ipa_reference_get_read_local (tree fn)
-{
- ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn);
- if (l)
- return l->statics_read;
- else
- return NULL;
-}
-
-/* Return a bitmap indexed by VAR_DECL uid for the static variables
- that may be written locally by the execution of the function fn.
- Returns NULL if no data is available. */
-
-bitmap
-ipa_reference_get_written_local (tree fn)
-{
- ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn);
- if (l)
- return l->statics_written;
- else
- return NULL;
-}
-
-/* Return a bitmap indexed by VAR_DECL uid for the static variables
that are read during the execution of the function FN. Returns
NULL if no data is available. */
bitmap
-ipa_reference_get_read_global (tree fn)
+ipa_reference_get_read_global (struct cgraph_node *fn)
{
ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
if (g)
@@ -195,7 +233,7 @@ ipa_reference_get_read_global (tree fn)
call. Returns NULL if no data is available. */
bitmap
-ipa_reference_get_written_global (tree fn)
+ipa_reference_get_written_global (struct cgraph_node *fn)
{
ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
if (g)
@@ -209,7 +247,7 @@ ipa_reference_get_written_global (tree fn)
NULL if no data is available. */
bitmap
-ipa_reference_get_not_read_global (tree fn)
+ipa_reference_get_not_read_global (struct cgraph_node *fn)
{
ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
if (g)
@@ -224,7 +262,7 @@ ipa_reference_get_not_read_global (tree fn)
call. Returns NULL if no data is available. */
bitmap
-ipa_reference_get_not_written_global (tree fn)
+ipa_reference_get_not_written_global (struct cgraph_node *fn)
{
ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
if (g)
@@ -360,7 +398,7 @@ check_call (ipa_reference_local_vars_info_t local, gimple stmt)
avail = cgraph_function_body_availability (callee);
}
- if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
+ if (avail <= AVAIL_OVERWRITABLE)
if (local)
{
if (flags & ECF_CONST)
@@ -393,7 +431,7 @@ scan_stmt_for_static_refs (gimple_stmt_iterator *gsip,
bitmap_iterator bi;
if (fn)
- local = get_reference_vars_info_from_cgraph (fn)->local;
+ local = get_reference_vars_info (fn)->local;
if (gimple_loaded_syms (stmt))
EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
@@ -472,30 +510,30 @@ get_static_name (int index)
return NULL;
}
-/* Or in all of the bits from every callee into X, the caller's, bit
- vector. There are several cases to check to avoid the sparse
+/* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
+ bit vector. There are several cases to check to avoid the sparse
bitmap oring. */
static void
-propagate_bits (struct cgraph_node *x)
+propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
{
- ipa_reference_vars_info_t x_info = get_reference_vars_info_from_cgraph (x);
- ipa_reference_global_vars_info_t x_global = x_info->global;
-
struct cgraph_edge *e;
for (e = x->callees; e; e = e->next_callee)
{
struct cgraph_node *y = e->callee;
/* Only look at the master nodes and skip external nodes. */
- y = cgraph_master_clone (y);
- if (y)
+ if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE)
{
- if (get_reference_vars_info_from_cgraph (y))
+ if (get_reference_vars_info (y))
{
ipa_reference_vars_info_t y_info
- = get_reference_vars_info_from_cgraph (y);
+ = get_reference_vars_info (y);
ipa_reference_global_vars_info_t y_global = y_info->global;
+
+ /* Calls in current cycle do not have global computed yet. */
+ if (!y_info->global)
+ continue;
if (x_global->statics_read
!= all_module_statics)
@@ -539,70 +577,6 @@ propagate_bits (struct cgraph_node *x)
}
}
-/* Look at all of the callees of X to see which ones represent inlined
- calls. For each of these callees, merge their local info into
- TARGET and check their children recursively.
-
- This function goes away when Jan changes the inliner and IPA
- analysis so that this is not run between the time when inlining
- decisions are made and when the inlining actually occurs. */
-
-static void
-merge_callee_local_info (struct cgraph_node *target,
- struct cgraph_node *x)
-{
- struct cgraph_edge *e;
- ipa_reference_local_vars_info_t x_l =
- get_reference_vars_info_from_cgraph (target)->local;
-
- /* Make the world safe for tail recursion. */
- struct ipa_dfs_info *node_info = (struct ipa_dfs_info *) x->aux;
-
- if (node_info->aux)
- return;
-
- node_info->aux = x;
-
- for (e = x->callees; e; e = e->next_callee)
- {
- struct cgraph_node *y = e->callee;
- if (y->global.inlined_to)
- {
- ipa_reference_vars_info_t y_info;
- ipa_reference_local_vars_info_t y_l;
- struct cgraph_node* orig_y = y;
-
- y = cgraph_master_clone (y);
- if (y)
- {
- y_info = get_reference_vars_info_from_cgraph (y);
- y_l = y_info->local;
- if (x_l != y_l)
- {
- bitmap_ior_into (x_l->statics_read,
- y_l->statics_read);
- bitmap_ior_into (x_l->statics_written,
- y_l->statics_written);
- }
- x_l->calls_read_all |= y_l->calls_read_all;
- x_l->calls_write_all |= y_l->calls_write_all;
- merge_callee_local_info (target, y);
- }
- else
- {
- fprintf(stderr, "suspect inlining of ");
- dump_cgraph_node (stderr, orig_y);
- fprintf(stderr, "\ninto ");
- dump_cgraph_node (stderr, target);
- dump_cgraph (stderr);
- gcc_assert(false);
- }
- }
- }
-
- node_info->aux = NULL;
-}
-
/* The init routine for analyzing global static variable usage. See
comments at top for description. */
static void
@@ -653,10 +627,9 @@ init_function_info (struct cgraph_node *fn)
= XCNEW (struct ipa_reference_vars_info_d);
ipa_reference_local_vars_info_t l
= XCNEW (struct ipa_reference_local_vars_info_d);
- tree decl = fn->decl;
/* Add the info to the tree's annotation. */
- get_function_ann (decl)->reference_vars_info = info;
+ set_reference_vars_info (fn, info);
info->local = l;
l->statics_read = BITMAP_ALLOC (&local_info_obstack);
@@ -728,18 +701,12 @@ analyze_function (struct cgraph_node *fn)
current_function_decl = NULL;
}
-/* If FN is avail == AVAIL_OVERWRITABLE, replace the effects bit
- vectors with worst case bit vectors. We had to analyze it above to
- find out if it took the address of any statics. However, now that
- we know that, we can get rid of all of the other side effects. */
-
+/* Remove local data associated with function FN. */
static void
-clean_function (struct cgraph_node *fn)
+clean_function_local_data (struct cgraph_node *fn)
{
- ipa_reference_vars_info_t info = get_reference_vars_info_from_cgraph (fn);
+ ipa_reference_vars_info_t info = get_reference_vars_info (fn);
ipa_reference_local_vars_info_t l = info->local;
- ipa_reference_global_vars_info_t g = info->global;
-
if (l)
{
if (l->statics_read
@@ -749,8 +716,19 @@ clean_function (struct cgraph_node *fn)
&&l->statics_written != all_module_statics)
BITMAP_FREE (l->statics_written);
free (l);
+ info->local = NULL;
}
+}
+
+/* Remove all data associated with function FN. */
+
+static void
+clean_function (struct cgraph_node *fn)
+{
+ ipa_reference_vars_info_t info = get_reference_vars_info (fn);
+ ipa_reference_global_vars_info_t g = info->global;
+ clean_function_local_data (fn);
if (g)
{
if (g->statics_read
@@ -769,10 +747,11 @@ clean_function (struct cgraph_node *fn)
&& g->statics_not_written != all_module_statics)
BITMAP_FREE (g->statics_not_written);
free (g);
+ info->global = NULL;
}
- free (get_function_ann (fn->decl)->reference_vars_info);
- get_function_ann (fn->decl)->reference_vars_info = NULL;
+ free (get_reference_vars_info (fn));
+ set_reference_vars_info (fn, NULL);
}
/* Called when new function is inserted to callgraph late. */
@@ -787,6 +766,76 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
visited_nodes = NULL;
}
+static bitmap
+copy_local_bitmap (bitmap src)
+{
+ bitmap dst;
+ if (!src)
+ return NULL;
+ if (src == all_module_statics)
+ return all_module_statics;
+ dst = BITMAP_ALLOC (&local_info_obstack);
+ bitmap_copy (dst, src);
+ return dst;
+}
+
+static bitmap
+copy_global_bitmap (bitmap src)
+{
+ bitmap dst;
+ if (!src)
+ return NULL;
+ if (src == all_module_statics)
+ return all_module_statics;
+ dst = BITMAP_ALLOC (&global_info_obstack);
+ bitmap_copy (dst, src);
+ return dst;
+}
+
+/* Called when new clone is inserted to callgraph late. */
+
+static void
+duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
+ void *data ATTRIBUTE_UNUSED)
+{
+ ipa_reference_global_vars_info_t ginfo;
+ ipa_reference_local_vars_info_t linfo;
+ ipa_reference_global_vars_info_t dst_ginfo;
+ ipa_reference_local_vars_info_t dst_linfo;
+
+ ginfo = get_global_reference_vars_info (src);
+ linfo = get_local_reference_vars_info (src);
+ if (!linfo && !ginfo)
+ return;
+ init_function_info (dst);
+ if (linfo)
+ {
+ dst_linfo = get_local_reference_vars_info (dst);
+ dst_linfo->statics_read = copy_local_bitmap (linfo->statics_read);
+ dst_linfo->statics_written = copy_local_bitmap (linfo->statics_written);
+ dst_linfo->calls_read_all = linfo->calls_read_all;
+ dst_linfo->calls_write_all = linfo->calls_write_all;
+ }
+ if (ginfo)
+ {
+ get_reference_vars_info (dst)->global = XCNEW (struct ipa_reference_global_vars_info_d);
+ dst_ginfo = get_global_reference_vars_info (dst);
+ dst_ginfo->statics_read = copy_global_bitmap (ginfo->statics_read);
+ dst_ginfo->statics_written = copy_global_bitmap (ginfo->statics_written);
+ dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read);
+ dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written);
+ }
+}
+
+/* Called when node is removed. */
+
+static void
+remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+{
+ if (get_reference_vars_info (node))
+ clean_function (node);
+}
+
/* Analyze each function in the cgraph to see which global or statics
are read or written. */
@@ -802,6 +851,10 @@ generate_summary (void)
function_insertion_hook_holder =
cgraph_add_function_insertion_hook (&add_new_function, NULL);
+ node_removal_hook_holder =
+ cgraph_add_node_removal_hook (&remove_node_data, NULL);
+ node_duplication_hook_holder =
+ cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
ipa_init ();
module_statics_readonly = BITMAP_ALLOC (&local_info_obstack);
bm_temp = BITMAP_ALLOC (&local_info_obstack);
@@ -822,10 +875,7 @@ generate_summary (void)
replaced with worst case info.
*/
for (node = cgraph_nodes; node; node = node->next)
- if (node->analyzed
- && (cgraph_is_master_clone (node)
- || (cgraph_function_body_availability (node)
- == AVAIL_OVERWRITABLE)))
+ if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
analyze_function (node);
pointer_set_destroy (visited_nodes);
@@ -890,13 +940,10 @@ generate_summary (void)
}
for (node = cgraph_nodes; node; node = node->next)
- if (node->analyzed
- && (cgraph_is_master_clone (node)
- || (cgraph_function_body_availability (node)
- == AVAIL_OVERWRITABLE)))
+ if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
{
ipa_reference_local_vars_info_t l;
- l = get_reference_vars_info_from_cgraph (node)->local;
+ l = get_reference_vars_info (node)->local;
/* Any variables that are not in all_module_statics are
removed from the local maps. This will include all of the
@@ -913,16 +960,13 @@ generate_summary (void)
if (dump_file)
for (node = cgraph_nodes; node; node = node->next)
- if (node->analyzed
- && (cgraph_is_master_clone (node)
- || (cgraph_function_body_availability (node)
- == AVAIL_OVERWRITABLE)))
+ if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
{
ipa_reference_local_vars_info_t l;
unsigned int index;
bitmap_iterator bi;
- l = get_reference_vars_info_from_cgraph (node)->local;
+ l = get_reference_vars_info (node)->local;
fprintf (dump_file,
"\nFunction name:%s/%i:",
cgraph_node_name (node), node->uid);
@@ -940,6 +984,10 @@ generate_summary (void)
fprintf(dump_file, "%s ",
get_static_name (index));
}
+ if (l->calls_read_all)
+ fprintf (dump_file, "\n calls read all: ");
+ if (l->calls_write_all)
+ fprintf (dump_file, "\n calls read all: ");
}
}
@@ -981,7 +1029,7 @@ propagate (void)
struct ipa_dfs_info * w_info;
node = order[i];
- node_info = get_reference_vars_info_from_cgraph (node);
+ node_info = get_reference_vars_info (node);
if (!node_info)
{
dump_cgraph_node (stderr, node);
@@ -989,7 +1037,7 @@ propagate (void)
gcc_unreachable ();
}
- node_info->global = node_g;
+ gcc_assert (!node_info->global);
node_l = node_info->local;
read_all = node_l->calls_read_all;
@@ -1002,7 +1050,7 @@ propagate (void)
while (w)
{
ipa_reference_local_vars_info_t w_l =
- get_reference_vars_info_from_cgraph (w)->local;
+ get_reference_vars_info (w)->local;
read_all |= w_l->calls_read_all;
write_all |= w_l->calls_write_all;
@@ -1029,16 +1077,14 @@ propagate (void)
node_l->statics_written);
}
+ propagate_bits (node_g, node);
w_info = (struct ipa_dfs_info *) node->aux;
w = w_info->next_cycle;
while (w)
{
ipa_reference_vars_info_t w_ri =
- get_reference_vars_info_from_cgraph (w);
+ get_reference_vars_info (w);
ipa_reference_local_vars_info_t w_l = w_ri->local;
-
- /* All nodes within a cycle share the same global info bitmaps. */
- w_ri->global = node_g;
/* These global bitmaps are initialized from the local info
of all of the nodes in the region. However there is no
@@ -1050,36 +1096,25 @@ propagate (void)
if (!write_all)
bitmap_ior_into (node_g->statics_written,
w_l->statics_written);
+ propagate_bits (node_g, w);
w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
- w = node;
- while (w)
- {
- propagate_bits (w);
- w_info = (struct ipa_dfs_info *) w->aux;
- w = w_info->next_cycle;
- }
- }
-
- /* Need to fix up the local information sets. The information that
- has been gathered so far is preinlining. However, the
- compilation will progress post inlining so the local sets for the
- inlined calls need to be merged into the callers. Note that the
- local sets are not shared between all of the nodes in a cycle so
- those nodes in the cycle must be processed explicitly. */
- for (i = 0; i < order_pos; i++ )
- {
- struct ipa_dfs_info * w_info;
- node = order[i];
- merge_callee_local_info (node, node);
-
+ /* All nodes within a cycle have the same global info bitmaps. */
+ node_info->global = node_g;
w_info = (struct ipa_dfs_info *) node->aux;
w = w_info->next_cycle;
while (w)
{
- merge_callee_local_info (w, w);
+ ipa_reference_vars_info_t w_ri =
+ get_reference_vars_info (w);
+
+ gcc_assert (!w_ri->global);
+ w_ri->global = XCNEW (struct ipa_reference_global_vars_info_d);
+ w_ri->global->statics_read = copy_global_bitmap (node_g->statics_read);
+ w_ri->global->statics_written = copy_global_bitmap (node_g->statics_written);
+
w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
@@ -1097,7 +1132,7 @@ propagate (void)
struct ipa_dfs_info * w_info;
node = order[i];
- node_info = get_reference_vars_info_from_cgraph (node);
+ node_info = get_reference_vars_info (node);
node_g = node_info->global;
node_l = node_info->local;
fprintf (dump_file,
@@ -1123,7 +1158,7 @@ propagate (void)
while (w)
{
ipa_reference_vars_info_t w_ri =
- get_reference_vars_info_from_cgraph (w);
+ get_reference_vars_info (w);
ipa_reference_local_vars_info_t w_l = w_ri->local;
fprintf (dump_file, "\n next cycle: %s/%i ",
cgraph_node_name (w), w->uid);
@@ -1170,7 +1205,7 @@ propagate (void)
ipa_reference_vars_info_t node_info;
ipa_reference_global_vars_info_t node_g;
node = order[i];
- node_info = get_reference_vars_info_from_cgraph (node);
+ node_info = get_reference_vars_info (node);
node_g = node_info->global;
/* Create the complimentary sets. These are more useful for
@@ -1179,11 +1214,9 @@ propagate (void)
node_g->statics_not_written = BITMAP_ALLOC (&global_info_obstack);
if (node_g->statics_read != all_module_statics)
- {
- bitmap_and_compl (node_g->statics_not_read,
- all_module_statics,
- node_g->statics_read);
- }
+ bitmap_and_compl (node_g->statics_not_read,
+ all_module_statics,
+ node_g->statics_read);
if (node_g->statics_written
!= all_module_statics)
@@ -1197,7 +1230,7 @@ propagate (void)
for (node = cgraph_nodes; node; node = node->next)
{
ipa_reference_vars_info_t node_info;
- node_info = get_reference_vars_info_from_cgraph (node);
+ node_info = get_reference_vars_info (node);
/* Get rid of the aux information. */
if (node->aux)
@@ -1206,19 +1239,10 @@ propagate (void)
node->aux = NULL;
}
- if (node->analyzed
- && (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE))
+ if (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE)
clean_function (node);
else if (node_info)
- {
- /* Remove local info we no longer need. */
- if (node_info->local->statics_read
- && node_info->local->statics_read != all_module_statics)
- BITMAP_FREE (node_info->local->statics_read);
- if (node_info->local->statics_written
- && node_info->local->statics_written != all_module_statics)
- BITMAP_FREE (node_info->local->statics_written);
- }
+ clean_function_local_data (node);
}
bitmap_obstack_release (&local_info_obstack);
return 0;
diff --git a/gcc/ipa-reference.h b/gcc/ipa-reference.h
index 1800a8ca9b9..7d5b36ed36b 100644
--- a/gcc/ipa-reference.h
+++ b/gcc/ipa-reference.h
@@ -23,60 +23,11 @@ along with GCC; see the file COPYING3. If not see
#include "bitmap.h"
#include "tree.h"
-/* The static variables defined within the compilation unit that are
- loaded or stored directly by function that owns this structure. */
-
-struct ipa_reference_local_vars_info_d
-{
- bitmap statics_read;
- bitmap statics_written;
-
- /* Set when this function calls another function external to the
- compilation unit or if the function has a asm clobber of memory.
- In general, such calls are modeled as reading and writing all
- variables (both bits on) but sometime there are attributes on the
- called function so we can do better. */
- bool calls_read_all;
- bool calls_write_all;
-};
-
-struct ipa_reference_global_vars_info_d
-{
- bitmap statics_read;
- bitmap statics_written;
- bitmap statics_not_read;
- bitmap statics_not_written;
-};
-
-/* Statics that are read and written by some set of functions. The
- local ones are based on the loads and stores local to the function.
- The global ones are based on the local info as well as the
- transitive closure of the functions that are called. The
- structures are separated to allow the global structures to be
- shared between several functions since every function within a
- strongly connected component will have the same information. This
- sharing saves both time and space in the computation of the vectors
- as well as their translation from decl_uid form to ann_uid
- form. */
-
-typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
-typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
-
-struct ipa_reference_vars_info_d
-{
- ipa_reference_local_vars_info_t local;
- ipa_reference_global_vars_info_t global;
-};
-
-typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
-
/* In ipa-reference.c */
-bitmap ipa_reference_get_read_local (tree fn);
-bitmap ipa_reference_get_written_local (tree fn);
-bitmap ipa_reference_get_read_global (tree fn);
-bitmap ipa_reference_get_written_global (tree fn);
-bitmap ipa_reference_get_not_read_global (tree fn);
-bitmap ipa_reference_get_not_written_global (tree fn);
+bitmap ipa_reference_get_read_global (struct cgraph_node *fn);
+bitmap ipa_reference_get_written_global (struct cgraph_node *fn);
+bitmap ipa_reference_get_not_read_global (struct cgraph_node *fn);
+bitmap ipa_reference_get_not_written_global (struct cgraph_node *fn);
#endif /* GCC_IPA_REFERENCE_H */
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index 729a84d8710..95e1856ac5b 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -100,10 +100,8 @@ searchc (struct searchc_env* env, struct cgraph_node *v)
{
struct ipa_dfs_info * w_info;
struct cgraph_node *w = edge->callee;
- /* Bypass the clones and only look at the master node. Skip
- external and other bogus nodes. */
- w = cgraph_master_clone (w);
- if (w && w->aux)
+
+ if (w->aux && cgraph_function_body_availability (edge->callee) > AVAIL_OVERWRITABLE)
{
w_info = (struct ipa_dfs_info *) w->aux;
if (w_info->new_node)
@@ -168,27 +166,29 @@ ipa_utils_reduced_inorder (struct cgraph_node **order,
env.reduce = reduce;
for (node = cgraph_nodes; node; node = node->next)
- if ((node->analyzed)
- && (cgraph_is_master_clone (node)
- || (allow_overwritable
- && (cgraph_function_body_availability (node) ==
- AVAIL_OVERWRITABLE))))
- {
- /* Reuse the info if it is already there. */
- struct ipa_dfs_info *info = (struct ipa_dfs_info *) node->aux;
- if (!info)
- info = XCNEW (struct ipa_dfs_info);
- info->new_node = true;
- info->on_stack = false;
- info->next_cycle = NULL;
- node->aux = info;
-
- splay_tree_insert (env.nodes_marked_new,
- (splay_tree_key)node->uid,
- (splay_tree_value)node);
- }
- else
- node->aux = NULL;
+ {
+ enum availability avail = cgraph_function_body_availability (node);
+
+ if (avail > AVAIL_OVERWRITABLE
+ || (allow_overwritable
+ && (avail == AVAIL_OVERWRITABLE)))
+ {
+ /* Reuse the info if it is already there. */
+ struct ipa_dfs_info *info = (struct ipa_dfs_info *) node->aux;
+ if (!info)
+ info = XCNEW (struct ipa_dfs_info);
+ info->new_node = true;
+ info->on_stack = false;
+ info->next_cycle = NULL;
+ node->aux = info;
+
+ splay_tree_insert (env.nodes_marked_new,
+ (splay_tree_key)node->uid,
+ (splay_tree_value)node);
+ }
+ else
+ node->aux = NULL;
+ }
result = splay_tree_min (env.nodes_marked_new);
while (result)
{
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 801d2debabb..96241889538 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -1653,8 +1653,8 @@ add_call_clobber_ops (gimple stmt, tree callee ATTRIBUTE_UNUSED)
/* Get info for local and module level statics. There is a bit
set for each static if the call being processed does not read
or write that variable. */
- not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL;
- not_written_b = callee ? ipa_reference_get_not_written_global (callee) : NULL;
+ not_read_b = callee ? ipa_reference_get_not_read_global (cgraph_node (callee)) : NULL;
+ not_written_b = callee ? ipa_reference_get_not_written_global (cgraph_node (callee)) : NULL;
/* Add a VDEF operand for every call clobbered variable. */
EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, u, bi)
@@ -1705,7 +1705,7 @@ add_call_read_ops (gimple stmt, tree callee ATTRIBUTE_UNUSED)
if (gimple_call_flags (stmt) & ECF_CONST)
return;
- not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL;
+ not_read_b = callee ? ipa_reference_get_not_read_global (cgraph_node (callee)) : NULL;
/* For pure functions we compute non-escaped uses separately. */
if (gimple_call_flags (stmt) & ECF_PURE)