summaryrefslogtreecommitdiff
path: root/gcc/cgraphbuild.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-04-22 10:21:45 +0000
committer <>2015-04-25 21:44:09 +0000
commitf80b5ea1605c9f9408c5aa386ba71c16d918ebbf (patch)
treebb7eafaa81fc4b8c5c215bc08d517fd158db234a /gcc/cgraphbuild.c
parentc27a97d04853380f1e80525391b3f0d156ed4c84 (diff)
downloadgcc-tarball-f80b5ea1605c9f9408c5aa386ba71c16d918ebbf.tar.gz
Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-5.1.0.tar.bz2.gcc-5.1.0
Diffstat (limited to 'gcc/cgraphbuild.c')
-rw-r--r--gcc/cgraphbuild.c302
1 files changed, 153 insertions, 149 deletions
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index 19961e27df..f2f04c34ca 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -1,5 +1,5 @@
/* Callgraph construction.
- Copyright (C) 2003-2014 Free Software Foundation, Inc.
+ Copyright (C) 2003-2015 Free Software Foundation, Inc.
Contributed by Jan Hubicka
This file is part of GCC.
@@ -22,8 +22,23 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
#include "tree.h"
-#include "pointer-set.h"
+#include "fold-const.h"
+#include "predict.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
#include "basic-block.h"
#include "tree-ssa-alias.h"
#include "internal-fn.h"
@@ -36,8 +51,15 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "intl.h"
#include "tree-pass.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
+#include "cgraph.h"
#include "ipa-utils.h"
#include "except.h"
+#include "alloc-pool.h"
+#include "symbol-summary.h"
+#include "ipa-prop.h"
#include "ipa-inline.h"
/* Context of record_reference. */
@@ -57,7 +79,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
{
tree t = *tp;
tree decl;
- struct record_reference_ctx *ctx = (struct record_reference_ctx *)data;
+ record_reference_ctx *ctx = (record_reference_ctx *)data;
t = canonicalize_constructor_val (t, NULL);
if (!t)
@@ -79,20 +101,16 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
decl = get_base_var (*tp);
if (TREE_CODE (decl) == FUNCTION_DECL)
{
- struct cgraph_node *node = cgraph_get_create_node (decl);
+ cgraph_node *node = cgraph_node::get_create (decl);
if (!ctx->only_vars)
- cgraph_mark_address_taken_node (node);
- ipa_record_reference (ctx->varpool_node,
- node,
- IPA_REF_ADDR, NULL);
+ node->mark_address_taken ();
+ ctx->varpool_node->create_reference (node, IPA_REF_ADDR);
}
if (TREE_CODE (decl) == VAR_DECL)
{
- varpool_node *vnode = varpool_node_for_decl (decl);
- ipa_record_reference (ctx->varpool_node,
- vnode,
- IPA_REF_ADDR, NULL);
+ varpool_node *vnode = varpool_node::get_create (decl);
+ ctx->varpool_node->create_reference (vnode, IPA_REF_ADDR);
}
*walk_subtrees = 0;
break;
@@ -114,7 +132,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
/* Record references to typeinfos in the type list LIST. */
static void
-record_type_list (struct cgraph_node *node, tree list)
+record_type_list (cgraph_node *node, tree list)
{
for (; list; list = TREE_CHAIN (list))
{
@@ -128,10 +146,8 @@ record_type_list (struct cgraph_node *node, tree list)
type = TREE_OPERAND (type, 0);
if (TREE_CODE (type) == VAR_DECL)
{
- varpool_node *vnode = varpool_node_for_decl (type);
- ipa_record_reference (node,
- vnode,
- IPA_REF_ADDR, NULL);
+ varpool_node *vnode = varpool_node::get_create (type);
+ node->create_reference (vnode, IPA_REF_ADDR);
}
}
}
@@ -141,17 +157,17 @@ record_type_list (struct cgraph_node *node, tree list)
for NODE. */
static void
-record_eh_tables (struct cgraph_node *node, struct function *fun)
+record_eh_tables (cgraph_node *node, function *fun)
{
eh_region i;
if (DECL_FUNCTION_PERSONALITY (node->decl))
{
tree per_decl = DECL_FUNCTION_PERSONALITY (node->decl);
- struct cgraph_node *per_node = cgraph_get_create_node (per_decl);
+ cgraph_node *per_node = cgraph_node::get_create (per_decl);
- ipa_record_reference (node, per_node, IPA_REF_ADDR, NULL);
- cgraph_mark_address_taken_node (per_node);
+ node->create_reference (per_node, IPA_REF_ADDR);
+ per_node->mark_address_taken ();
}
i = fun->eh->region_tree;
@@ -229,20 +245,16 @@ mark_address (gimple stmt, tree addr, tree, void *data)
addr = get_base_address (addr);
if (TREE_CODE (addr) == FUNCTION_DECL)
{
- struct cgraph_node *node = cgraph_get_create_node (addr);
- cgraph_mark_address_taken_node (node);
- ipa_record_reference ((symtab_node *)data,
- node,
- IPA_REF_ADDR, stmt);
+ cgraph_node *node = cgraph_node::get_create (addr);
+ node->mark_address_taken ();
+ ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt);
}
else if (addr && TREE_CODE (addr) == VAR_DECL
&& (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
{
- varpool_node *vnode = varpool_node_for_decl (addr);
+ varpool_node *vnode = varpool_node::get_create (addr);
- ipa_record_reference ((symtab_node *)data,
- vnode,
- IPA_REF_ADDR, stmt);
+ ((symtab_node *)data)->create_reference (vnode, IPA_REF_ADDR, stmt);
}
return false;
@@ -258,20 +270,16 @@ mark_load (gimple stmt, tree t, tree, void *data)
{
/* ??? This can happen on platforms with descriptors when these are
directly manipulated in the code. Pretend that it's an address. */
- struct cgraph_node *node = cgraph_get_create_node (t);
- cgraph_mark_address_taken_node (node);
- ipa_record_reference ((symtab_node *)data,
- node,
- IPA_REF_ADDR, stmt);
+ cgraph_node *node = cgraph_node::get_create (t);
+ node->mark_address_taken ();
+ ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt);
}
else if (t && TREE_CODE (t) == VAR_DECL
&& (TREE_STATIC (t) || DECL_EXTERNAL (t)))
{
- varpool_node *vnode = varpool_node_for_decl (t);
+ varpool_node *vnode = varpool_node::get_create (t);
- ipa_record_reference ((symtab_node *)data,
- vnode,
- IPA_REF_LOAD, stmt);
+ ((symtab_node *)data)->create_reference (vnode, IPA_REF_LOAD, stmt);
}
return false;
}
@@ -285,39 +293,64 @@ mark_store (gimple stmt, tree t, tree, void *data)
if (t && TREE_CODE (t) == VAR_DECL
&& (TREE_STATIC (t) || DECL_EXTERNAL (t)))
{
- varpool_node *vnode = varpool_node_for_decl (t);
+ varpool_node *vnode = varpool_node::get_create (t);
- ipa_record_reference ((symtab_node *)data,
- vnode,
- IPA_REF_STORE, stmt);
+ ((symtab_node *)data)->create_reference (vnode, IPA_REF_STORE, stmt);
}
return false;
}
-/* Record all references from NODE that are taken in statement STMT. */
+/* Record all references from cgraph_node that are taken in statement STMT. */
+
void
-ipa_record_stmt_references (struct cgraph_node *node, gimple stmt)
+cgraph_node::record_stmt_references (gimple stmt)
{
- walk_stmt_load_store_addr_ops (stmt, node, mark_load, mark_store,
+ walk_stmt_load_store_addr_ops (stmt, this, mark_load, mark_store,
mark_address);
}
/* Create cgraph edges for function calls.
Also look for functions and variables having addresses taken. */
-static unsigned int
-build_cgraph_edges (void)
+namespace {
+
+const pass_data pass_data_build_cgraph_edges =
+{
+ GIMPLE_PASS, /* type */
+ "*build_cgraph_edges", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_build_cgraph_edges : public gimple_opt_pass
+{
+public:
+ pass_build_cgraph_edges (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_build_cgraph_edges, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual unsigned int execute (function *);
+
+}; // class pass_build_cgraph_edges
+
+unsigned int
+pass_build_cgraph_edges::execute (function *fun)
{
basic_block bb;
- struct cgraph_node *node = cgraph_get_node (current_function_decl);
- struct pointer_set_t *visited_nodes = pointer_set_create ();
+ cgraph_node *node = cgraph_node::get (current_function_decl);
gimple_stmt_iterator gsi;
tree decl;
unsigned ix;
/* Create the callgraph edges and record the nodes referenced by the function.
body. */
- FOR_EACH_BB_FN (bb, cfun)
+ FOR_EACH_BB_FN (bb, fun)
{
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
@@ -327,89 +360,54 @@ build_cgraph_edges (void)
if (is_gimple_debug (stmt))
continue;
- if (is_gimple_call (stmt))
+ if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
{
int freq = compute_call_stmt_bb_frequency (current_function_decl,
bb);
- decl = gimple_call_fndecl (stmt);
+ decl = gimple_call_fndecl (call_stmt);
if (decl)
- cgraph_create_edge (node, cgraph_get_create_node (decl),
- stmt, bb->count, freq);
- else if (gimple_call_internal_p (stmt))
+ node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count, freq);
+ else if (gimple_call_internal_p (call_stmt))
;
else
- cgraph_create_indirect_edge (node, stmt,
- gimple_call_flags (stmt),
- bb->count, freq);
+ node->create_indirect_edge (call_stmt,
+ gimple_call_flags (call_stmt),
+ bb->count, freq);
}
- ipa_record_stmt_references (node, stmt);
- if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
- && gimple_omp_parallel_child_fn (stmt))
+ node->record_stmt_references (stmt);
+ if (gomp_parallel *omp_par_stmt = dyn_cast <gomp_parallel *> (stmt))
{
- tree fn = gimple_omp_parallel_child_fn (stmt);
- ipa_record_reference (node,
- cgraph_get_create_node (fn),
- IPA_REF_ADDR, stmt);
+ tree fn = gimple_omp_parallel_child_fn (omp_par_stmt);
+ node->create_reference (cgraph_node::get_create (fn),
+ IPA_REF_ADDR, stmt);
}
if (gimple_code (stmt) == GIMPLE_OMP_TASK)
{
tree fn = gimple_omp_task_child_fn (stmt);
if (fn)
- ipa_record_reference (node,
- cgraph_get_create_node (fn),
- IPA_REF_ADDR, stmt);
+ node->create_reference (cgraph_node::get_create (fn),
+ IPA_REF_ADDR, stmt);
fn = gimple_omp_task_copy_fn (stmt);
if (fn)
- ipa_record_reference (node,
- cgraph_get_create_node (fn),
- IPA_REF_ADDR, stmt);
+ node->create_reference (cgraph_node::get_create (fn),
+ IPA_REF_ADDR, stmt);
}
}
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- ipa_record_stmt_references (node, gsi_stmt (gsi));
+ node->record_stmt_references (gsi_stmt (gsi));
}
/* Look for initializers of constant variables and private statics. */
- FOR_EACH_LOCAL_DECL (cfun, ix, decl)
+ FOR_EACH_LOCAL_DECL (fun, ix, decl)
if (TREE_CODE (decl) == VAR_DECL
&& (TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
&& !DECL_HAS_VALUE_EXPR_P (decl))
- varpool_finalize_decl (decl);
- record_eh_tables (node, cfun);
+ varpool_node::finalize_decl (decl);
+ record_eh_tables (node, fun);
- pointer_set_destroy (visited_nodes);
return 0;
}
-namespace {
-
-const pass_data pass_data_build_cgraph_edges =
-{
- GIMPLE_PASS, /* type */
- "*build_cgraph_edges", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- false, /* has_gate */
- true, /* has_execute */
- TV_NONE, /* tv_id */
- PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_build_cgraph_edges : public gimple_opt_pass
-{
-public:
- pass_build_cgraph_edges (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_build_cgraph_edges, ctxt)
- {}
-
- /* opt_pass methods: */
- unsigned int execute () { return build_cgraph_edges (); }
-
-}; // class pass_build_cgraph_edges
-
} // anon namespace
gimple_opt_pass *
@@ -425,29 +423,28 @@ make_pass_build_cgraph_edges (gcc::context *ctxt)
void
record_references_in_initializer (tree decl, bool only_vars)
{
- struct pointer_set_t *visited_nodes = pointer_set_create ();
- varpool_node *node = varpool_node_for_decl (decl);
- struct record_reference_ctx ctx = {false, NULL};
+ varpool_node *node = varpool_node::get_create (decl);
+ hash_set<tree> visited_nodes;
+ record_reference_ctx ctx = {false, NULL};
ctx.varpool_node = node;
ctx.only_vars = only_vars;
walk_tree (&DECL_INITIAL (decl), record_reference,
- &ctx, visited_nodes);
- pointer_set_destroy (visited_nodes);
+ &ctx, &visited_nodes);
}
/* Rebuild cgraph edges for current function node. This needs to be run after
passes that don't update the cgraph. */
unsigned int
-rebuild_cgraph_edges (void)
+cgraph_edge::rebuild_edges (void)
{
basic_block bb;
- struct cgraph_node *node = cgraph_get_node (current_function_decl);
+ cgraph_node *node = cgraph_node::get (current_function_decl);
gimple_stmt_iterator gsi;
- cgraph_node_remove_callees (node);
- ipa_remove_all_references (&node->ref_list);
+ node->remove_callees ();
+ node->remove_all_references ();
node->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
@@ -458,48 +455,52 @@ rebuild_cgraph_edges (void)
gimple stmt = gsi_stmt (gsi);
tree decl;
- if (is_gimple_call (stmt))
+ if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
{
int freq = compute_call_stmt_bb_frequency (current_function_decl,
bb);
- decl = gimple_call_fndecl (stmt);
+ decl = gimple_call_fndecl (call_stmt);
if (decl)
- cgraph_create_edge (node, cgraph_get_create_node (decl), stmt,
- bb->count, freq);
- else if (gimple_call_internal_p (stmt))
+ node->create_edge (cgraph_node::get_create (decl), call_stmt,
+ bb->count, freq);
+ else if (gimple_call_internal_p (call_stmt))
;
else
- cgraph_create_indirect_edge (node, stmt,
- gimple_call_flags (stmt),
- bb->count, freq);
+ node->create_indirect_edge (call_stmt,
+ gimple_call_flags (call_stmt),
+ bb->count, freq);
}
- ipa_record_stmt_references (node, stmt);
+ node->record_stmt_references (stmt);
}
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- ipa_record_stmt_references (node, gsi_stmt (gsi));
+ node->record_stmt_references (gsi_stmt (gsi));
}
record_eh_tables (node, cfun);
gcc_assert (!node->global.inlined_to);
+ if (node->instrumented_version
+ && !node->instrumentation_clone)
+ node->create_reference (node->instrumented_version, IPA_REF_CHKP, NULL);
+
return 0;
}
-/* Rebuild cgraph edges for current function node. This needs to be run after
- passes that don't update the cgraph. */
+/* Rebuild cgraph references for current function node. This needs to be run
+ after passes that don't update the cgraph. */
void
-cgraph_rebuild_references (void)
+cgraph_edge::rebuild_references (void)
{
basic_block bb;
- struct cgraph_node *node = cgraph_get_node (current_function_decl);
+ cgraph_node *node = cgraph_node::get (current_function_decl);
gimple_stmt_iterator gsi;
- struct ipa_ref *ref;
+ ipa_ref *ref = NULL;
int i;
/* Keep speculative references for further cgraph edge expansion. */
- for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref);)
+ for (i = 0; node->iterate_reference (i, ref);)
if (!ref->speculative)
- ipa_remove_reference (ref);
+ ref->remove_reference ();
else
i++;
@@ -508,11 +509,15 @@ cgraph_rebuild_references (void)
FOR_EACH_BB_FN (bb, cfun)
{
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- ipa_record_stmt_references (node, gsi_stmt (gsi));
+ node->record_stmt_references (gsi_stmt (gsi));
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- ipa_record_stmt_references (node, gsi_stmt (gsi));
+ node->record_stmt_references (gsi_stmt (gsi));
}
record_eh_tables (node, cfun);
+
+ if (node->instrumented_version
+ && !node->instrumentation_clone)
+ node->create_reference (node->instrumented_version, IPA_REF_CHKP, NULL);
}
namespace {
@@ -522,8 +527,6 @@ const pass_data pass_data_rebuild_cgraph_edges =
GIMPLE_PASS, /* type */
"*rebuild_cgraph_edges", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- false, /* has_gate */
- true, /* has_execute */
TV_CGRAPH, /* tv_id */
PROP_cfg, /* properties_required */
0, /* properties_provided */
@@ -541,7 +544,10 @@ public:
/* opt_pass methods: */
opt_pass * clone () { return new pass_rebuild_cgraph_edges (m_ctxt); }
- unsigned int execute () { return rebuild_cgraph_edges (); }
+ virtual unsigned int execute (function *)
+ {
+ return cgraph_edge::rebuild_edges ();
+ }
}; // class pass_rebuild_cgraph_edges
@@ -554,15 +560,6 @@ make_pass_rebuild_cgraph_edges (gcc::context *ctxt)
}
-static unsigned int
-remove_cgraph_callee_edges (void)
-{
- struct cgraph_node *node = cgraph_get_node (current_function_decl);
- cgraph_node_remove_callees (node);
- ipa_remove_all_references (&node->ref_list);
- return 0;
-}
-
namespace {
const pass_data pass_data_remove_cgraph_callee_edges =
@@ -570,8 +567,6 @@ const pass_data pass_data_remove_cgraph_callee_edges =
GIMPLE_PASS, /* type */
"*remove_cgraph_callee_edges", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- false, /* has_gate */
- true, /* has_execute */
TV_NONE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
@@ -591,10 +586,19 @@ public:
opt_pass * clone () {
return new pass_remove_cgraph_callee_edges (m_ctxt);
}
- unsigned int execute () { return remove_cgraph_callee_edges (); }
+ virtual unsigned int execute (function *);
}; // class pass_remove_cgraph_callee_edges
+unsigned int
+pass_remove_cgraph_callee_edges::execute (function *)
+{
+ cgraph_node *node = cgraph_node::get (current_function_decl);
+ node->remove_callees ();
+ node->remove_all_references ();
+ return 0;
+}
+
} // anon namespace
gimple_opt_pass *