{
if (!t) return;
- if ((TREE_CODE (t) == VAR_DECL)
+ if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
&& (has_proper_scope_for_analysis (t)))
{
if (checking_write)
if (TREE_CODE (t) == ADDR_EXPR)
{
tree x = get_base_var (t);
- if (TREE_CODE (x) == VAR_DECL)
+ if (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == FUNCTION_DECL)
if (has_proper_scope_for_analysis (x))
bitmap_set_bit (module_statics_escape, DECL_UID (x));
}
check_call (ipa_reference_local_vars_info_t local, tree call_expr)
{
int flags = call_expr_flags (call_expr);
- tree operand_list = TREE_OPERAND (call_expr, 1);
tree operand;
tree callee_t = get_callee_fndecl (call_expr);
enum availability avail = AVAIL_NOT_AVAILABLE;
+ call_expr_arg_iterator iter;
- for (operand = operand_list;
- operand != NULL_TREE;
- operand = TREE_CHAIN (operand))
- {
- tree argument = TREE_VALUE (operand);
- check_rhs_var (local, argument);
- }
+ FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr)
+ check_rhs_var (local, operand);
if (callee_t)
{
int *walk_subtrees,
void *data)
{
- struct cgraph_node *fn = data;
+ struct cgraph_node *fn = (struct cgraph_node *) data;
tree t = *tp;
ipa_reference_local_vars_info_t local = NULL;
if (fn)
*walk_subtrees = 0;
break;
- case MODIFY_EXPR:
+ case GIMPLE_MODIFY_STMT:
{
/* First look on the lhs and see what variable is stored to */
- tree lhs = TREE_OPERAND (t, 0);
- tree rhs = TREE_OPERAND (t, 1);
+ tree lhs = GIMPLE_STMT_OPERAND (t, 0);
+ tree rhs = GIMPLE_STMT_OPERAND (t, 1);
check_lhs_var (local, lhs);
/* For the purposes of figuring out what the cast affects */
switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
{
case tcc_binary:
+ case tcc_comparison:
{
tree op0 = TREE_OPERAND (rhs, 0);
tree op1 = TREE_OPERAND (rhs, 1);
case ADDR_EXPR:
check_rhs_var (local, rhs);
break;
- case CALL_EXPR:
+ default:
+ break;
+ }
+ break;
+ case tcc_vl_exp:
+ switch (TREE_CODE (rhs))
+ {
+ case CALL_EXPR:
check_call (local, rhs);
break;
default:
get_reference_vars_info_from_cgraph (target)->local;
/* Make the world safe for tail recursion. */
- struct ipa_dfs_info *node_info = x->aux;
+ struct ipa_dfs_info *node_info = (struct ipa_dfs_info *) x->aux;
if (node_info->aux)
return;
static void
ipa_init (void)
{
+ struct cgraph_node *node;
memory_identifier_string = build_string(7, "memory");
reference_vars_to_consider =
module_statics_written = BITMAP_ALLOC (&ipa_obstack);
all_module_statics = BITMAP_ALLOC (&ipa_obstack);
+ /* This will add NODE->DECL to the splay trees. */
+ for (node = cgraph_nodes; node; node = node->next)
+ has_proper_scope_for_analysis (node->decl);
+
/* 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
to variables defined within this unit. */
static void
-analyze_variable (struct cgraph_varpool_node *vnode)
+analyze_variable (struct varpool_node *vnode)
{
tree global = vnode->decl;
- if (TREE_CODE (global) == VAR_DECL)
- {
- if (DECL_INITIAL (global))
- walk_tree (&DECL_INITIAL (global), scan_for_static_refs,
- NULL, visited_nodes);
- }
- else gcc_unreachable ();
+ walk_tree (&DECL_INITIAL (global), scan_for_static_refs,
+ NULL, visited_nodes);
}
/* This is the main routine for finding the reference patterns for
analyze_function (struct cgraph_node *fn)
{
ipa_reference_vars_info_t info
- = xcalloc (1, sizeof (struct ipa_reference_vars_info_d));
+ = XCNEW (struct ipa_reference_vars_info_d);
ipa_reference_local_vars_info_t l
- = xcalloc (1, sizeof (struct ipa_reference_local_vars_info_d));
+ = XCNEW (struct ipa_reference_local_vars_info_d);
tree decl = fn->decl;
/* Add the info to the tree's annotation. */
FOR_EACH_BB_FN (this_block, this_cfun)
{
block_stmt_iterator bsi;
+ tree phi, op;
+ use_operand_p use;
+ ssa_op_iter iter;
+
+ /* Find the addresses taken in phi node arguments. */
+ for (phi = phi_nodes (this_block); phi; phi = PHI_CHAIN (phi))
+ {
+ FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
+ {
+ op = USE_FROM_PTR (use);
+ if (TREE_CODE (op) == ADDR_EXPR)
+ check_rhs_var (l, op);
+ }
+ }
+
for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
walk_tree (bsi_stmt_ptr (bsi), scan_for_static_refs,
fn, visited_nodes);
on the local information that was produced by ipa_analyze_function
and ipa_analyze_variable. */
-static void
+static unsigned int
static_execute (void)
{
struct cgraph_node *node;
- struct cgraph_varpool_node *vnode;
+ struct varpool_node *vnode;
struct cgraph_node *w;
struct cgraph_node **order =
- xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
- int order_pos = order_pos = ipa_utils_reduced_inorder (order, false, true);
+ XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
+ int order_pos = ipa_utils_reduced_inorder (order, false, true);
int i;
ipa_init ();
/* Process all of the variables first. */
- for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
+ FOR_EACH_STATIC_INITIALIZER (vnode)
analyze_variable (vnode);
/* Process all of the functions next.
{
tree var = get_static_decl (index);
+ /* Readonly on a function decl is very different from the
+ variable. */
+ if (TREE_CODE (var) == FUNCTION_DECL)
+ continue;
+
/* Ignore variables in named sections - changing TREE_READONLY
changes the section flags, potentially causing conflicts with
other variables in the same named section. */
{
ipa_reference_vars_info_t node_info;
ipa_reference_global_vars_info_t node_g =
- xcalloc (1, sizeof (struct ipa_reference_global_vars_info_d));
+ XCNEW (struct ipa_reference_global_vars_info_d);
ipa_reference_local_vars_info_t node_l;
bool read_all;
/* If any node in a cycle is calls_read_all or calls_write_all
they all are. */
- w_info = node->aux;
+ w_info = (struct ipa_dfs_info *) node->aux;
w = w_info->next_cycle;
while (w)
{
read_all |= w_l->calls_read_all;
write_all |= w_l->calls_write_all;
- w_info = w->aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
node_l->statics_written);
}
- w_info = node->aux;
+ w_info = (struct ipa_dfs_info *) node->aux;
w = w_info->next_cycle;
while (w)
{
if (!write_all)
bitmap_ior_into (node_g->statics_written,
w_l->statics_written);
- w_info = w->aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
while (w)
{
propagate_bits (w);
- w_info = w->aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
}
node = order[i];
merge_callee_local_info (node, node);
- w_info = node->aux;
+ w_info = (struct ipa_dfs_info *) node->aux;
w = w_info->next_cycle;
while (w)
{
merge_callee_local_info (w, w);
- w_info = w->aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
}
get_static_name (index));
}
- w_info = node->aux;
+ w_info = (struct ipa_dfs_info *) node->aux;
w = w_info->next_cycle;
while (w)
{
}
- w_info = w->aux;
+ w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
}
fprintf (dump_file, "\n globals read: ");
&& (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE))
clean_function (node);
}
+ return 0;
}