Commit e2c9111c by Jan Hubicka Committed by Jan Hubicka

re PR middle-end/37448 (cannot compile big function)

	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.

From-SVN: r140463
parent 52d1bfd8
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
......
......@@ -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 *
......
......@@ -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));
}
......
......@@ -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 */
......@@ -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)
{
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment