public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Remove (lots of) lazy call graph node construction
@ 2011-03-19 19:29 Martin Jambor
  2011-03-19 19:30 ` [PATCH 4/4] Tweaks to objc -> call graph interface Martin Jambor
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Martin Jambor @ 2011-03-19 19:29 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jan Hubicka

Hi,

I believe the general consensus is that lazy call graph node creation
is no longer a good idea and a few of us have seen bugs caused by a
creation of a node when we did not expect it.  Therefore I embarked on
getting rid of it.  In the process I quickly realized it would be
difficult to do that completely but it is certainly possible to weed
it out of most places where it is not necessary.  We can then tackle
the remaining places separately.

These patches are meant to be applied on top of
http://gcc.gnu.org/ml/gcc-patches/2011-03/msg01170.html

The first patch in the series removes the cgraph_node function.  Most
of its callers should use already existing cgraph_get_node instead,
for the others there are new functions:

- craph_create_node will create a node but fail on assert if there
  already is a node for the declaration

- cgraph_get_create_node is the new lazy node creation.  I did not
  want to continue using cgraph_node name because I really thought the
  it was unfortunate and the new name will also help us to discourage
  potential new uses and isolate those that we might want to convert
  to a non-lazy way of creating nodes later.

- cgraph_do_get_node is a simple wrapper around cgraph_get_node which
  checking_asserts that the return value is not NULL.  I found it very
  useful while developing the patch and think it can be sometimes
  useful even in the longer term, for example when the result is
  stored in some data structure which is to be used later.  If the
  general consensus is that we don't want it, it is easy to remove it
  from the patch.

When I was processing calls to cgraph_node I first tried to determine
if it is possible for cgraph_get_node to return NULL.  If it was, I
either lazily-created the node or assumed the default node properties
depending on the nature of the call.  If I thought NULL should not be
returned, I used cgraph_do_get_node if the code would not immediately
segfault.

The places which still need lazy node construction can be roughly
divided into the following categories:

- Stuff called from the front ends.  Most noticeably, nested functions
  are organized in a tree of call graph nodes for some time, the
  leaves are entered first and the cgraph_(create_)node creates the
  encapsulation one for DECL_CONTEXT.  And then there are aliases.
  And perhaps more stuff I already forgot about.  In most cases,
  keeping it is not harmful and even sensible.

- Almost all of cgraphbuild.c.  But that basically makes sense.

- Sometimes the decl of call statement is a builtin that is newly
  created by folding.  If it does not have a node at that point, we
  might trigger an assert.

I have tried to verify diligently that NULL cannot be returned at
places where I don't handle it and of course I tested the changes
thoroughly.  Nevertheless, there are few places where I'd appreciate
if someone confirmed my conclusions.  These are:
- lower_emutls_function_body honk and
- hunks in ipa-struct-reorg.c and ipa-type-escape.c ...just in case
  anyone really cared ;-)

The patch is not very complex but I understand the scope it changes is
vast.  In order to ease its assessment, all changes in front-ends
change calls to cgraph_node to calls to cgraph_get_create_node (except
an obvious assert in java).  I hope that this will mean the big first
patch will eventually not require approval of individual front-end
maintainers.  There are three simple subsequent patches which change
the calls in front-end specific code but those are much smaller and
not that crucial to the whole effort.

I have successfully bootstrapped and tested "all,ada" on x86_64-linux
and "c,c++,fortran" on i686.  I have successfully checked
"c,c++,fortran" on ia64 and (an almost identical patch) on sparc64.

Sorry for the long email and long patch to review.  I understand there
will be comments and suggestions and I thank in advance for them.  At
the same time I think it is really a good idea to commit something
like this early in stage 1.  Tomorrow I'm leaving for a four day
vacation (I'll be back on Thursday) so please be patient when waiting
for my reply.

Thanks!

Martin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 3/4] A tweak to fortran -> call graph interface
  2011-03-19 19:29 [PATCH 0/4] Remove (lots of) lazy call graph node construction Martin Jambor
                   ` (2 preceding siblings ...)
  2011-03-19 19:30 ` [PATCH 1/4] Remove cgraph_node function and fixup all callers Martin Jambor
@ 2011-03-19 19:30 ` Martin Jambor
  2011-03-23 16:57   ` Jan Hubicka
  2011-03-23  8:53 ` [PATCH 0/4] Remove (lots of) lazy call graph node construction Jan Hubicka
  4 siblings, 1 reply; 13+ messages in thread
From: Martin Jambor @ 2011-03-19 19:30 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jan Hubicka

[-- Attachment #1: cgraph_fortran_calls.diff --]
[-- Type: text/plain, Size: 900 bytes --]

Hi,

it seems to me that fortran can call cgraph_create_node directly
without checking for its existence first.

Thanks,

Martin


2011-03-18  Martin Jambor  <mjambor@suse.cz>

	* trans-decl.c (gfc_generate_function_code): Call cgraph_create_node
	instead of cgraph_get_create_node.

Index: src/gcc/fortran/trans-decl.c
===================================================================
--- src.orig/gcc/fortran/trans-decl.c	2011-03-18 19:45:10.000000000 +0100
+++ src/gcc/fortran/trans-decl.c	2011-03-18 19:45:12.000000000 +0100
@@ -4924,7 +4924,7 @@ gfc_generate_function_code (gfc_namespac
   if (decl_function_context (fndecl))
     /* Register this function with cgraph just far enough to get it
        added to our parent's nested function list.  */
-    (void) cgraph_get_create_node (fndecl);
+    (void) cgraph_create_node (fndecl);
   else
     cgraph_finalize_function (fndecl, true);
 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 4/4] Tweaks to objc -> call graph interface
  2011-03-19 19:29 [PATCH 0/4] Remove (lots of) lazy call graph node construction Martin Jambor
@ 2011-03-19 19:30 ` Martin Jambor
  2011-03-23 16:56   ` Jan Hubicka
  2011-03-19 19:30 ` [PATCH 2/4] Tweaks to C++ " Martin Jambor
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Martin Jambor @ 2011-03-19 19:30 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jan Hubicka

[-- Attachment #1: cgraph_objc_calls.diff --]
[-- Type: text/plain, Size: 1148 bytes --]

Hi,

thi is really only based on successful testing and not much analyzis
of the context but it seems that we don't need lazy node construction
here.  It would be nice not to have it after the big patch gets in.

Thanks,

Martin


2011-03-18  Martin Jambor  <mjambor@suse.cz>

	* objc-act.c (mark_referenced_methods): Call cgraph_do_get_node
	instead of cgraph_get_create_node.

Index: src/gcc/objc/objc-act.c
===================================================================
--- src.orig/gcc/objc/objc-act.c	2011-03-18 20:21:00.000000000 +0100
+++ src/gcc/objc/objc-act.c	2011-03-18 20:21:05.000000000 +0100
@@ -4520,7 +4520,7 @@ mark_referenced_methods (void)
       while (chain)
 	{
 	  cgraph_mark_needed_node (
-			   cgraph_get_create_node (METHOD_DEFINITION (chain)));
+			       cgraph_do_get_node (METHOD_DEFINITION (chain)));
 	  chain = DECL_CHAIN (chain);
 	}
 
@@ -4528,7 +4528,7 @@ mark_referenced_methods (void)
       while (chain)
 	{
 	  cgraph_mark_needed_node (
-			   cgraph_get_create_node (METHOD_DEFINITION (chain)));
+			       cgraph_do_get_node (METHOD_DEFINITION (chain)));
 	  chain = DECL_CHAIN (chain);
 	}
     }

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/4] Remove cgraph_node function and fixup all callers
  2011-03-19 19:29 [PATCH 0/4] Remove (lots of) lazy call graph node construction Martin Jambor
  2011-03-19 19:30 ` [PATCH 4/4] Tweaks to objc -> call graph interface Martin Jambor
  2011-03-19 19:30 ` [PATCH 2/4] Tweaks to C++ " Martin Jambor
@ 2011-03-19 19:30 ` Martin Jambor
  2011-03-23  9:09   ` Jan Hubicka
  2011-03-19 19:30 ` [PATCH 3/4] A tweak to fortran -> call graph interface Martin Jambor
  2011-03-23  8:53 ` [PATCH 0/4] Remove (lots of) lazy call graph node construction Jan Hubicka
  4 siblings, 1 reply; 13+ messages in thread
From: Martin Jambor @ 2011-03-19 19:30 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jan Hubicka

[-- Attachment #1: no_cgraph_node.diff --]
[-- Type: text/plain, Size: 58482 bytes --]

Hi,

I hope I explained everything in the introductory email.  This patch
is the core, the subsequent ones are only small tweaks in the front
ends.

Let me remind you this is to be applied on top of
http://gcc.gnu.org/ml/gcc-patches/2011-03/msg01170.html.  (I have
tested the patch on top revision 171141.)

Thanks,

Martin



2011-03-18  Martin Jambor  <mjambor@suse.cz>

	* cgraph.h (cgraph_node): Remove function declaration.
	(cgraph_create_node): Declare.
	(cgraph_get_create_node): Likewise.
	(cgraph_do_get_node): New function.

	* cgraph.c (cgraph_create_node): Renamed to cgraph_create_node_1.
	Updated all callers.
	(cgraph_node): Renamed to cgraph_create_node, assert that a node for
	the decl does not already exist.  Call cgraph_get_create_node instead
	of cgraph_node.
	(cgraph_get_create_node): New function.
	(cgraph_same_body_alias): Update comment.
	(cgraph_set_call_stmt): Call cgraph_do_get_node instead of cgraph_node.
	(cgraph_update_edges_for_call_stmt): Likewise.
	(cgraph_clone_edge): Likewise.
	(cgraph_create_virtual_clone): Likewise.
	(cgraph_set_call_stmt): Call cgraph_get_create_node instead of
	cgraph_node.
	(cgraph_local_info): Call cgraph_get_node instead of cgraph_node,
	handle NULL return value.
	(cgraph_global_info): Likewise.
	(cgraph_rtl_info): Likewise.
	(cgraph_add_new_function): Call cgraph_create_node or
	cgraph_get_create_node instead of cgraph_node.

	* cgraphbuild.c (record_reference): Call cgraph_get_create_node
	instead of cgraph_node.
	(record_eh_tables): Likewise.
	(mark_address): Likewise.
	(mark_load): Likewise.
	(build_cgraph_edges): Call cgraph_get_node and cgraph_get_create_node
	instead of cgraph_node.
	(rebuild_cgraph_edges): Likewise.
	(cgraph_rebuild_references): Call cgraph_get_node instead of
	cgraph_node.
	(remove_cgraph_callee_edges): Likewise.

	* cgraphunit.c (cgraph_finalize_function): Call cgraph_get_create_node
	instead of cgraph_node.
	(cgraph_mark_if_needed): Call cgraph_get_node instead of cgraph_node.
	(verify_cgraph_node): Likewise.
	(cgraph_analyze_functions): Likewise.
	(cgraph_preserve_function_body_p): Likewise.
	(save_inline_function_body): Likewise.
	(save_inline_function_body): Likewise.
	(cgraph_copy_node_for_versioning): Call cgraph_create_node instead of
	cgraph_node.

	* tree-inline.c (copy_bb): Call cgraph_get_node instead of cgraph_node.
	(estimate_num_insns): Likewise and handle returned NULL.
	(optimize_inline_calls): Call cgraph_get_node instead of cgraph_node.
	(tree_function_versioning): Call cgraph_do_get_node instead of
	cgraph_node.

	* lto-symtab.c (lto_symtab_merge_cgraph_nodes_1): Call
	cgraph_create_node instead of cgraph_node.

	* c-decl.c (finish_function): Call cgraph_get_create_node instead
	of cgraph_node.
	* c-family/c-gimplify.c (c_genericize): Likewise.
	* lto-cgraph.c (input_node): Likewise.
	* lto-streamer-in.c (input_function): Likewise.

	* except.c (set_nothrow_function_flags): Call cgraph_get_node instead
	of cgraph_node.
	* final.c (rest_of_clean_state): Likewise.
	* gimple-iterator.c (update_call_edge_frequencies): Likewise.
	* passes.c (pass_init_dump_file): Likewise.
	(execute_all_ipa_transforms): Likewise.
	(function_called_by_processed_nodes_p): Likewise.
	* predict.c (maybe_hot_frequency_p): Likewise.
	(probably_never_executed_bb_p): Likewise.
	(compute_function_frequency): Likewise.
	* tree-nested.c (check_for_nested_with_variably_modified): Likewise.
	(unnest_nesting_tree_1): Likewise.
	(lower_nested_functions): Likewise.
	* tree-optimize.c (execute_fixup_cfg): Likewise.
	(tree_rest_of_compilation): Likewise.
	* tree-optimize.c (execute_fixup_cfg): Likewise.
	(tree_rest_of_compilation): Likewise.
	* tree-profile.c (gimple_gen_ic_func_profiler): Likewise.
	* tree-sra.c (ipa_early_sra): Likewise.
	* tree-ssa-loop-ivopts.c (computation_cost): Likewise.
	* config/i386/i386.c (ix86_compute_frame_layout): Likewise.
	* ipa.c (record_cdtor_fn): Likewise.
	* ipa-inline.c (cgraph_early_inlining): Likewise.
	(compute_inline_parameters_for_current): Likewise.
	* ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
	* ipa-pure-const.c (local_pure_const): Likewise.
	* ipa-split.c (split_function): Likewise.
	(split_function): Likewise.
	(execute_split_functions): Likewise.

	* lto-streamer-in.c (lto_read_body): Call cgraph_do_get_node instead
	of cgraph_node.
	* omp-low.c (new_omp_context): Likewise.
	(create_task_copyfn): Likewise.
	* tree-emutls.c (lower_emutls_function_body): Likewise.
	* ipa-struct-reorg.c (update_cgraph_with_malloc_call): Likewise.
	* ipa-type-escape.c (check_call): Likewise.
	* matrix-reorg.c (transform_allocation_sites): Likewise.

	* gimplify.c (unshare_body): Call cgraph_get_node instead of
	cgraph_node, handle NULL return value.
	(unvisit_body): Likewise.
	(gimplify_body): Likewise.
	* predict.c (optimize_function_for_size_p): Likewise.
	* tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Likewise.
	(call_may_clobber_ref_p_1): Likewise.

	* varasm.c (function_section_1): Call cgraph_get_node instead of
	cgraph_node and handle returned NULL.
	(assemble_start_function): Likewise.
	(mark_decl_referenced): Call cgraph_get_create_node instead of
	cgraph_node.
	(assemble_alias): Likewise.

gcc/c-family/
	* c-gimplify.c (c_genericize): Call cgraph_get_create_node instead

gcc/cp/
	* cp/class.c (cp_fold_obj_type_ref): Call cgraph_get_create_node
	instead of cgraph_node.
	* cp/decl2.c (cxx_callgraph_analyze_expr): Likewise.
	(cp_write_global_declarations): Likewise.
	* cp/optimize.c (maybe_clone_body): Likewise.
	(maybe_clone_body): Likewise.
	* cp/semantics.c (maybe_add_lambda_conv_op): Likewise.
	* cp/mangle.c (mangle_decl): Likewise.
	* cp/method.c (make_alias_for_thunk): Likewise.
	(use_thunk): Likewise.

gcc/ada/
	* gcc-interface/utils.c (end_subprog_body): Call
	cgraph_get_create_node instead of cgraph_node.

gcc/fortran/
	* trans-decl.c (gfc_generate_function_code): Call
	cgraph_get_create_node instead of cgraph_node.

gcc/java/
	* decl.c (java_mark_decl_local): Call cgraph_get_node instead of
	cgraph_node and handle returned NULL.

gcc/objc/
	* objc-act.c (mark_referenced_methods): Call cgraph_get_create_node
	instead of cgraph_node.


Index: src/gcc/c-decl.c
===================================================================
--- src.orig/gcc/c-decl.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/c-decl.c	2011-03-19 01:54:42.000000000 +0100
@@ -8338,7 +8338,7 @@ finish_function (void)
 	  /* Register this function with cgraph just far enough to get it
 	    added to our parent's nested function list.  Handy, since the
 	    C front end doesn't have such a list.  */
-	  (void) cgraph_node (fndecl);
+	  (void) cgraph_get_create_node (fndecl);
 	}
     }
 
Index: src/gcc/c-family/c-gimplify.c
===================================================================
--- src.orig/gcc/c-family/c-gimplify.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/c-family/c-gimplify.c	2011-03-19 01:54:42.000000000 +0100
@@ -98,7 +98,7 @@ c_genericize (tree fndecl)
     }
 
   /* Dump all nested functions now.  */
-  cgn = cgraph_node (fndecl);
+  cgn = cgraph_get_create_node (fndecl);
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
     c_genericize (cgn->decl);
 }
Index: src/gcc/cgraph.c
===================================================================
--- src.orig/gcc/cgraph.c	2011-03-19 01:38:30.000000000 +0100
+++ src/gcc/cgraph.c	2011-03-19 01:56:01.000000000 +0100
@@ -466,7 +466,7 @@ cgraph_allocate_node (void)
 /* Allocate new callgraph node and insert it into basic data structures.  */
 
 static struct cgraph_node *
-cgraph_create_node (void)
+cgraph_create_node_1 (void)
 {
   struct cgraph_node *node = cgraph_allocate_node ();
 
@@ -488,7 +488,7 @@ cgraph_create_node (void)
 /* Return cgraph node assigned to DECL.  Create new one when needed.  */
 
 struct cgraph_node *
-cgraph_node (tree decl)
+cgraph_create_node (tree decl)
 {
   struct cgraph_node key, *node, **slot;
 
@@ -498,23 +498,15 @@ cgraph_node (tree decl)
     cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
 
   key.decl = decl;
-
   slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT);
+  gcc_assert (!*slot);
 
-  if (*slot)
-    {
-      node = *slot;
-      if (node->same_body_alias)
-	node = node->same_body;
-      return node;
-    }
-
-  node = cgraph_create_node ();
+  node = cgraph_create_node_1 ();
   node->decl = decl;
   *slot = node;
   if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
     {
-      node->origin = cgraph_node (DECL_CONTEXT (decl));
+      node->origin = cgraph_get_create_node (DECL_CONTEXT (decl));
       node->next_nested = node->origin->nested;
       node->origin->nested = node;
     }
@@ -536,6 +528,21 @@ cgraph_node (tree decl)
   return node;
 }
 
+/* Try to find a call graph node for declaration DECL and if it does not exist,
+   create it.  */
+
+struct cgraph_node *
+cgraph_get_create_node (tree decl)
+{
+  struct cgraph_node *node;
+
+  node = cgraph_get_node (decl);
+  if (node)
+    return node;
+
+  return cgraph_create_node (decl);
+}
+
 /* Mark ALIAS as an alias to DECL.  DECL_NODE is cgraph node representing
    the function body is associated with (not neccesarily cgraph_node (DECL).  */
 
@@ -570,9 +577,9 @@ cgraph_same_body_alias_1 (struct cgraph_
 }
 
 /* Attempt to mark ALIAS as an alias to DECL.  Return alias node if successful
-   and NULL otherwise. 
+   and NULL otherwise.
    Same body aliases are output whenever the body of DECL is output,
-   and cgraph_node (ALIAS) transparently returns cgraph_node (DECL).   */
+   and cgraph_get_node (ALIAS) transparently returns cgraph_get_node (DECL).  */
 
 struct cgraph_node *
 cgraph_same_body_alias (struct cgraph_node *decl_node, tree alias, tree decl)
@@ -859,7 +866,7 @@ cgraph_set_call_stmt (struct cgraph_edge
     {
       /* Constant propagation (and possibly also inlining?) can turn an
 	 indirect call into a direct one.  */
-      struct cgraph_node *new_callee = cgraph_node (decl);
+      struct cgraph_node *new_callee = cgraph_do_get_node (decl);
 
       cgraph_make_edge_direct (e, new_callee, 0);
     }
@@ -1299,7 +1306,7 @@ cgraph_update_edges_for_call_stmt_node (
 
       if (new_call)
 	{
-	  ne = cgraph_create_edge (node, cgraph_node (new_call),
+	  ne = cgraph_create_edge (node, cgraph_get_create_node (new_call),
 				   new_stmt, count, frequency,
 				   loop_nest);
 	  gcc_assert (ne->inline_failed);
@@ -1317,7 +1324,7 @@ cgraph_update_edges_for_call_stmt_node (
 void
 cgraph_update_edges_for_call_stmt (gimple old_stmt, tree old_decl, gimple new_stmt)
 {
-  struct cgraph_node *orig = cgraph_node (cfun->decl);
+  struct cgraph_node *orig = cgraph_do_get_node (cfun->decl);
   struct cgraph_node *node;
 
   cgraph_update_edges_for_call_stmt_node (orig, old_stmt, old_decl, new_stmt);
@@ -1764,7 +1771,9 @@ cgraph_local_info (tree decl)
   struct cgraph_node *node;
 
   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
-  node = cgraph_node (decl);
+  node = cgraph_get_node (decl);
+  if (!node)
+    return NULL;
   return &node->local;
 }
 
@@ -1776,7 +1785,9 @@ cgraph_global_info (tree decl)
   struct cgraph_node *node;
 
   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL && cgraph_global_info_ready);
-  node = cgraph_node (decl);
+  node = cgraph_get_node (decl);
+  if (!node)
+    return NULL;
   return &node->global;
 }
 
@@ -1788,9 +1799,10 @@ cgraph_rtl_info (tree decl)
   struct cgraph_node *node;
 
   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
-  node = cgraph_node (decl);
-  if (decl != current_function_decl
-      && !TREE_ASM_WRITTEN (node->decl))
+  node = cgraph_get_node (decl);
+  if (!node
+      || (decl != current_function_decl
+	  && !TREE_ASM_WRITTEN (node->decl)))
     return NULL;
   return &node->rtl;
 }
@@ -2116,7 +2128,7 @@ cgraph_clone_edge (struct cgraph_edge *e
 
       if (call_stmt && (decl = gimple_call_fndecl (call_stmt)))
 	{
-	  struct cgraph_node *callee = cgraph_node (decl);
+	  struct cgraph_node *callee = cgraph_do_get_node (decl);
 	  new_edge = cgraph_create_edge (n, callee, call_stmt, count, freq,
 					 e->loop_nest + loop_nest);
 	}
@@ -2170,7 +2182,7 @@ cgraph_clone_node (struct cgraph_node *n
 		   int loop_nest, bool update_original,
 		   VEC(cgraph_edge_p,heap) *redirect_callers)
 {
-  struct cgraph_node *new_node = cgraph_create_node ();
+  struct cgraph_node *new_node = cgraph_create_node_1 ();
   struct cgraph_edge *e;
   gcov_type count_scale;
   unsigned i;
@@ -2346,7 +2358,7 @@ cgraph_create_virtual_clone (struct cgra
       /* Record references of the future statement initializing the constant
 	 argument.  */
       if (TREE_CODE (var) == FUNCTION_DECL)
-	ipa_record_reference (new_node, NULL, cgraph_node (var),
+	ipa_record_reference (new_node, NULL, cgraph_do_get_node (var),
 			      NULL, IPA_REF_ADDR, NULL);
       else if (TREE_CODE (var) == VAR_DECL)
 	ipa_record_reference (new_node, NULL, NULL, varpool_node (var),
@@ -2455,7 +2467,7 @@ cgraph_add_new_function (tree fndecl, bo
     {
       case CGRAPH_STATE_CONSTRUCTION:
 	/* Just enqueue function to be processed at nearest occurrence.  */
-	node = cgraph_node (fndecl);
+	node = cgraph_create_node (fndecl);
 	node->next_needed = cgraph_new_nodes;
 	if (lowered)
 	  node->lowered = true;
@@ -2467,7 +2479,7 @@ cgraph_add_new_function (tree fndecl, bo
       case CGRAPH_STATE_EXPANSION:
 	/* Bring the function into finalized state and enqueue for later
 	   analyzing and compilation.  */
-	node = cgraph_node (fndecl);
+	node = cgraph_get_create_node (fndecl);
 	node->local.local = false;
 	node->local.finalized = true;
 	node->reachable = node->needed = true;
@@ -2495,7 +2507,7 @@ cgraph_add_new_function (tree fndecl, bo
       case CGRAPH_STATE_FINISHED:
 	/* At the very end of compilation we have to do all the work up
 	   to expansion.  */
-	node = cgraph_node (fndecl);
+	node = cgraph_create_node (fndecl);
 	if (lowered)
 	  node->lowered = true;
 	cgraph_analyze_function (node);
Index: src/gcc/cgraph.h
===================================================================
--- src.orig/gcc/cgraph.h	2011-03-19 01:31:22.000000000 +0100
+++ src/gcc/cgraph.h	2011-03-19 01:54:42.000000000 +0100
@@ -558,7 +558,8 @@ struct cgraph_edge *cgraph_create_indire
 struct cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
 struct cgraph_node * cgraph_get_node (const_tree);
 struct cgraph_node * cgraph_get_node_or_alias (const_tree);
-struct cgraph_node * cgraph_node (tree);
+struct cgraph_node * cgraph_create_node (tree);
+struct cgraph_node * cgraph_get_create_node (tree);
 struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree);
 struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, HOST_WIDE_INT,
 				       HOST_WIDE_INT, tree, tree);
@@ -614,6 +615,16 @@ bool resolution_used_from_other_file_p (
 bool cgraph_used_from_object_file_p (struct cgraph_node *node);
 bool varpool_used_from_object_file_p (struct varpool_node *node);
 
+/* Like cgraph_get_node but asserting the result is non-NULL if checking is
+   enabled.  */
+static inline struct cgraph_node *
+cgraph_do_get_node (const_tree fndecl)
+{
+  struct cgraph_node *node = cgraph_get_node (fndecl);
+  gcc_checking_assert (node);
+  return node;
+}
+
 /* In cgraphunit.c  */
 extern FILE *cgraph_dump_file;
 void cgraph_finalize_function (tree, bool);
Index: src/gcc/except.c
===================================================================
--- src.orig/gcc/except.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/except.c	2011-03-19 01:54:42.000000000 +0100
@@ -1879,11 +1879,11 @@ set_nothrow_function_flags (void)
 	  }
       }
   if (crtl->nothrow
-      && (cgraph_function_body_availability (cgraph_node
+      && (cgraph_function_body_availability (cgraph_get_node
 					     (current_function_decl))
           >= AVAIL_AVAILABLE))
     {
-      struct cgraph_node *node = cgraph_node (current_function_decl);
+      struct cgraph_node *node = cgraph_get_node (current_function_decl);
       struct cgraph_edge *e;
       for (e = node->callers; e; e = e->next_caller)
         e->can_throw_external = false;
Index: src/gcc/final.c
===================================================================
--- src.orig/gcc/final.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/final.c	2011-03-19 01:54:42.000000000 +0100
@@ -4364,7 +4364,7 @@ rest_of_clean_state (void)
       else
 	{
 	  const char *aname;
-	  struct cgraph_node *node = cgraph_node (current_function_decl);
+	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
 
 	  aname = (IDENTIFIER_POINTER
 		   (DECL_ASSEMBLER_NAME (current_function_decl)));
Index: src/gcc/gimple-iterator.c
===================================================================
--- src.orig/gcc/gimple-iterator.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/gimple-iterator.c	2011-03-19 01:54:42.000000000 +0100
@@ -84,7 +84,7 @@ update_call_edge_frequencies (gimple_seq
 	   to avoid calling them if we never see any calls.  */
 	if (cfun_node == NULL)
 	  {
-	    cfun_node = cgraph_node (current_function_decl);
+	    cfun_node = cgraph_get_node (current_function_decl);
 	    bb_freq = (compute_call_stmt_bb_frequency
 		       (current_function_decl, bb));
 	  }
Index: src/gcc/gimplify.c
===================================================================
--- src.orig/gcc/gimplify.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/gimplify.c	2011-03-19 01:54:42.000000000 +0100
@@ -959,11 +959,11 @@ copy_if_shared (tree *tp)
 static void
 unshare_body (tree *body_p, tree fndecl)
 {
-  struct cgraph_node *cgn = cgraph_node (fndecl);
+  struct cgraph_node *cgn = cgraph_get_node (fndecl);
 
   copy_if_shared (body_p);
 
-  if (body_p == &DECL_SAVED_TREE (fndecl))
+  if (cgn && body_p == &DECL_SAVED_TREE (fndecl))
     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
       unshare_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
 }
@@ -1000,11 +1000,11 @@ unmark_visited (tree *tp)
 static void
 unvisit_body (tree *body_p, tree fndecl)
 {
-  struct cgraph_node *cgn = cgraph_node (fndecl);
+  struct cgraph_node *cgn = cgraph_get_node (fndecl);
 
   unmark_visited (body_p);
 
-  if (body_p == &DECL_SAVED_TREE (fndecl))
+  if (cgn && body_p == &DECL_SAVED_TREE (fndecl))
     for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
       unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
 }
@@ -7679,6 +7679,7 @@ gimplify_body (tree *body_p, tree fndecl
   gimple_seq parm_stmts, seq;
   gimple outer_bind;
   struct gimplify_ctx gctx;
+  struct cgraph_node *cgn;
 
   timevar_push (TV_TREE_GIMPLIFY);
 
@@ -7696,7 +7697,8 @@ gimplify_body (tree *body_p, tree fndecl
   unshare_body (body_p, fndecl);
   unvisit_body (body_p, fndecl);
 
-  if (cgraph_node (fndecl)->origin)
+  cgn = cgraph_get_node (fndecl);
+  if (cgn && cgn->origin)
     nonlocal_vlas = pointer_set_create ();
 
   /* Make sure input_location isn't set to something weird.  */
Index: src/gcc/lto-cgraph.c
===================================================================
--- src.orig/gcc/lto-cgraph.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/lto-cgraph.c	2011-03-19 01:54:42.000000000 +0100
@@ -1044,7 +1044,7 @@ input_node (struct lto_file_decl_data *f
 				0, CGRAPH_FREQ_BASE, 0, false, NULL);
     }
   else
-    node = cgraph_node (fn_decl);
+    node = cgraph_get_create_node (fn_decl);
 
   node->count = lto_input_sleb128 (ib);
   node->count_materialization_scale = lto_input_sleb128 (ib);
Index: src/gcc/lto-streamer-in.c
===================================================================
--- src.orig/gcc/lto-streamer-in.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/lto-streamer-in.c	2011-03-19 01:54:42.000000000 +0100
@@ -1257,7 +1257,7 @@ input_function (tree fn_decl, struct dat
   DECL_INITIAL (fn_decl) = lto_input_tree (ib, data_in);
   gcc_assert (DECL_INITIAL (fn_decl));
   DECL_SAVED_TREE (fn_decl) = NULL_TREE;
-  node = cgraph_node (fn_decl);
+  node = cgraph_get_create_node (fn_decl);
 
   /* Read all the basic blocks.  */
   tag = input_record_start (ib);
@@ -1398,7 +1398,7 @@ lto_read_body (struct lto_file_decl_data
     {
       struct function *fn = DECL_STRUCT_FUNCTION (fn_decl);
       struct lto_in_decl_state *decl_state;
-      struct cgraph_node *node = cgraph_node (fn_decl);
+      struct cgraph_node *node = cgraph_do_get_node (fn_decl);
 
       push_cfun (fn);
       init_tree_ssa (fn);
Index: src/gcc/lto-symtab.c
===================================================================
--- src.orig/gcc/lto-symtab.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/lto-symtab.c	2011-03-19 01:54:42.000000000 +0100
@@ -799,7 +799,7 @@ lto_symtab_merge_cgraph_nodes_1 (void **
 	     previously unused.  Create the node.  */
 	  if (!prevailing->node)
 	    {
-	      prevailing->node = cgraph_node (prevailing->decl);
+	      prevailing->node = cgraph_create_node (prevailing->decl);
 	      prevailing->node->alias = true;
 	    }
 	  lto_cgraph_replace_node (e->node, prevailing->node);
Index: src/gcc/omp-low.c
===================================================================
--- src.orig/gcc/omp-low.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/omp-low.c	2011-03-19 01:54:42.000000000 +0100
@@ -1209,7 +1209,7 @@ new_omp_context (gimple stmt, omp_contex
     {
       ctx->cb.src_fn = current_function_decl;
       ctx->cb.dst_fn = current_function_decl;
-      ctx->cb.src_node = cgraph_node (current_function_decl);
+      ctx->cb.src_node = cgraph_do_get_node (current_function_decl);
       ctx->cb.dst_node = ctx->cb.src_node;
       ctx->cb.src_cfun = cfun;
       ctx->cb.copy_decl = omp_copy_decl;
@@ -6263,7 +6263,7 @@ create_task_copyfn (gimple task_stmt, om
       memset (&tcctx, '\0', sizeof (tcctx));
       tcctx.cb.src_fn = ctx->cb.src_fn;
       tcctx.cb.dst_fn = child_fn;
-      tcctx.cb.src_node = cgraph_node (tcctx.cb.src_fn);
+      tcctx.cb.src_node = cgraph_do_get_node (tcctx.cb.src_fn);
       tcctx.cb.dst_node = tcctx.cb.src_node;
       tcctx.cb.src_cfun = ctx->cb.src_cfun;
       tcctx.cb.copy_decl = task_copyfn_copy_decl;
Index: src/gcc/passes.c
===================================================================
--- src.orig/gcc/passes.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/passes.c	2011-03-19 01:54:42.000000000 +0100
@@ -1344,7 +1344,7 @@ pass_init_dump_file (struct opt_pass *pa
       if (dump_file && current_function_decl)
 	{
 	  const char *dname, *aname;
-	  struct cgraph_node *node = cgraph_node (current_function_decl);
+	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
 	  dname = lang_hooks.decl_printable_name (current_function_decl, 2);
 	  aname = (IDENTIFIER_POINTER
 		   (DECL_ASSEMBLER_NAME (current_function_decl)));
@@ -1476,7 +1476,7 @@ execute_all_ipa_transforms (void)
   struct cgraph_node *node;
   if (!cfun)
     return;
-  node = cgraph_node (current_function_decl);
+  node = cgraph_get_node (current_function_decl);
 
   if (node->ipa_transforms_to_apply)
     {
@@ -2030,7 +2030,9 @@ bool
 function_called_by_processed_nodes_p (void)
 {
   struct cgraph_edge *e;
-  for (e = cgraph_node (current_function_decl)->callers; e; e = e->next_caller)
+  for (e = cgraph_get_node (current_function_decl)->callers;
+       e;
+       e = e->next_caller)
     {
       if (e->caller->decl == current_function_decl)
         continue;
Index: src/gcc/predict.c
===================================================================
--- src.orig/gcc/predict.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/predict.c	2011-03-19 01:54:42.000000000 +0100
@@ -113,7 +113,7 @@ static const struct predictor_info predi
 static inline bool
 maybe_hot_frequency_p (int freq)
 {
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   if (!profile_info || !flag_branch_probabilities)
     {
       if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
@@ -203,7 +203,8 @@ probably_never_executed_bb_p (const_basi
   if (profile_info && flag_branch_probabilities)
     return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
   if ((!profile_info || !flag_branch_probabilities)
-      && cgraph_node (current_function_decl)->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
+      && (cgraph_get_node (current_function_decl)->frequency
+	  == NODE_FREQUENCY_UNLIKELY_EXECUTED))
     return true;
   return false;
 }
@@ -213,10 +214,11 @@ probably_never_executed_bb_p (const_basi
 bool
 optimize_function_for_size_p (struct function *fun)
 {
+  struct cgraph_node *node;
   return (optimize_size
 	  || (fun && fun->decl
-	      && (cgraph_node (fun->decl)->frequency
-		  == NODE_FREQUENCY_UNLIKELY_EXECUTED)));
+	      && (node = cgraph_get_node (fun->decl))
+	      && (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)));
 }
 
 /* Return true when current function should always be optimized for speed.  */
@@ -2225,7 +2227,7 @@ void
 compute_function_frequency (void)
 {
   basic_block bb;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   if (DECL_STATIC_CONSTRUCTOR (current_function_decl)
       || MAIN_NAME_P (DECL_NAME (current_function_decl)))
     node->only_called_at_startup = true;
Index: src/gcc/tree-emutls.c
===================================================================
--- src.orig/gcc/tree-emutls.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/tree-emutls.c	2011-03-19 01:54:42.000000000 +0100
@@ -619,7 +619,7 @@ lower_emutls_function_body (struct cgrap
 
   d.cfun_node = node;
   d.builtin_decl = built_in_decls[BUILT_IN_EMUTLS_GET_ADDRESS];
-  d.builtin_node = cgraph_node (d.builtin_decl);
+  d.builtin_node = cgraph_do_get_node (d.builtin_decl);
 
   FOR_EACH_BB (d.bb)
     {
Index: src/gcc/tree-nested.c
===================================================================
--- src.orig/gcc/tree-nested.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/tree-nested.c	2011-03-19 01:54:42.000000000 +0100
@@ -693,7 +693,7 @@ walk_all_functions (walk_stmt_fn callbac
 static bool
 check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
 {
-  struct cgraph_node *cgn = cgraph_node (fndecl);
+  struct cgraph_node *cgn = cgraph_get_node (fndecl);
   tree arg;
 
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
@@ -2523,13 +2523,13 @@ finalize_nesting_tree (struct nesting_in
 static void
 unnest_nesting_tree_1 (struct nesting_info *root)
 {
-  struct cgraph_node *node = cgraph_node (root->context);
+  struct cgraph_node *node = cgraph_get_node (root->context);
 
   /* For nested functions update the cgraph to reflect unnesting.
      We also delay finalizing of these functions up to this point.  */
   if (node->origin)
     {
-       cgraph_unnest_node (cgraph_node (root->context));
+       cgraph_unnest_node (node);
        cgraph_finalize_function (root->context, true);
     }
 }
@@ -2583,7 +2583,7 @@ lower_nested_functions (tree fndecl)
   struct nesting_info *root;
 
   /* If there are no nested functions, there's nothing to do.  */
-  cgn = cgraph_node (fndecl);
+  cgn = cgraph_get_node (fndecl);
   if (!cgn->nested)
     return;
 
Index: src/gcc/tree-optimize.c
===================================================================
--- src.orig/gcc/tree-optimize.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/tree-optimize.c	2011-03-19 01:54:42.000000000 +0100
@@ -247,12 +247,13 @@ execute_fixup_cfg (void)
   edge_iterator ei;
 
   if (ENTRY_BLOCK_PTR->count)
-    count_scale = (cgraph_node (current_function_decl)->count * REG_BR_PROB_BASE
-    		   + ENTRY_BLOCK_PTR->count / 2) / ENTRY_BLOCK_PTR->count;
+    count_scale = ((cgraph_get_node (current_function_decl)->count
+		    * REG_BR_PROB_BASE + ENTRY_BLOCK_PTR->count / 2)
+		   / ENTRY_BLOCK_PTR->count);
   else
     count_scale = REG_BR_PROB_BASE;
 
-  ENTRY_BLOCK_PTR->count = cgraph_node (current_function_decl)->count;
+  ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count;
   EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale
   			   + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
 
@@ -457,7 +458,7 @@ tree_rest_of_compilation (tree fndecl)
 
   gimple_set_body (fndecl, NULL);
   if (DECL_STRUCT_FUNCTION (fndecl) == 0
-      && !cgraph_node (fndecl)->origin)
+      && !cgraph_get_node (fndecl)->origin)
     {
       /* Stop pointing to the local nodes about to be freed.
 	 But DECL_INITIAL must remain nonzero so we know this
Index: src/gcc/tree-profile.c
===================================================================
--- src.orig/gcc/tree-profile.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/tree-profile.c	2011-03-19 01:54:42.000000000 +0100
@@ -346,7 +346,7 @@ gimple_gen_ic_profiler (histogram_value
 void
 gimple_gen_ic_func_profiler (void)
 {
-  struct cgraph_node * c_node = cgraph_node (current_function_decl);
+  struct cgraph_node * c_node = cgraph_get_node (current_function_decl);
   gimple_stmt_iterator gsi;
   gimple stmt1, stmt2;
   tree tree_uid, cur_func, counter_ptr, ptr_var, void0;
Index: src/gcc/tree-sra.c
===================================================================
--- src.orig/gcc/tree-sra.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/tree-sra.c	2011-03-19 01:54:42.000000000 +0100
@@ -4501,7 +4501,7 @@ ipa_sra_preliminary_function_checks (str
 static unsigned int
 ipa_early_sra (void)
 {
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   ipa_parm_adjustment_vec adjustments;
   int ret = 0;
 
Index: src/gcc/tree-ssa-alias.c
===================================================================
--- src.orig/gcc/tree-ssa-alias.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/tree-ssa-alias.c	2011-03-19 01:54:42.000000000 +0100
@@ -1246,14 +1246,15 @@ ref_maybe_used_by_call_p_1 (gimple call,
 
   /* Check if base is a global static variable that is not read
      by the function.  */
-  if (TREE_CODE (base) == VAR_DECL
+  if (callee != NULL_TREE
+      && TREE_CODE (base) == VAR_DECL
       && TREE_STATIC (base))
     {
+      struct cgraph_node *node = cgraph_get_node (callee);
       bitmap not_read;
 
-      if (callee != NULL_TREE
-	  && (not_read
-	        = ipa_reference_get_not_read_global (cgraph_node (callee)))
+      if (node
+	  && (not_read = ipa_reference_get_not_read_global (node))
 	  && bitmap_bit_p (not_read, DECL_UID (base)))
 	goto process_args;
     }
@@ -1513,10 +1514,11 @@ call_may_clobber_ref_p_1 (gimple call, a
       && TREE_CODE (base) == VAR_DECL
       && TREE_STATIC (base))
     {
+      struct cgraph_node *node = cgraph_get_node (callee);
       bitmap not_written;
 
-      if ((not_written
-	     = ipa_reference_get_not_written_global (cgraph_node (callee)))
+      if (node
+	  && (not_written = ipa_reference_get_not_written_global (node))
 	  && bitmap_bit_p (not_written, DECL_UID (base)))
 	return false;
     }
Index: src/gcc/tree-ssa-loop-ivopts.c
===================================================================
--- src.orig/gcc/tree-ssa-loop-ivopts.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/tree-ssa-loop-ivopts.c	2011-03-19 01:54:42.000000000 +0100
@@ -2849,7 +2849,7 @@ computation_cost (tree expr, bool speed)
   unsigned cost;
   /* Avoid using hard regs in ways which may be unsupported.  */
   int regno = LAST_VIRTUAL_REGISTER + 1;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   enum node_frequency real_frequency = node->frequency;
 
   node->frequency = NODE_FREQUENCY_NORMAL;
Index: src/gcc/cgraphbuild.c
===================================================================
--- src.orig/gcc/cgraphbuild.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/cgraphbuild.c	2011-03-19 01:54:42.000000000 +0100
@@ -68,9 +68,9 @@ record_reference (tree *tp, int *walk_su
       if (TREE_CODE (decl) == FUNCTION_DECL)
 	{
 	  if (!ctx->only_vars)
-	  cgraph_mark_address_taken_node (cgraph_node (decl));
+	    cgraph_mark_address_taken_node (cgraph_get_create_node (decl));
 	  ipa_record_reference (NULL, ctx->varpool_node,
-			        cgraph_node (decl), NULL,
+			        cgraph_get_node (decl), NULL,
 			        IPA_REF_ADDR, NULL);
 	}
 
@@ -143,8 +143,8 @@ record_eh_tables (struct cgraph_node *no
 
   if (DECL_FUNCTION_PERSONALITY (node->decl))
     ipa_record_reference (node, NULL,
-			  cgraph_node (DECL_FUNCTION_PERSONALITY (node->decl)),
-			  NULL, IPA_REF_ADDR, NULL);
+	       cgraph_get_create_node (DECL_FUNCTION_PERSONALITY (node->decl)),
+	       NULL, IPA_REF_ADDR, NULL);
 
   i = fun->eh->region_tree;
   if (!i)
@@ -244,7 +244,7 @@ mark_address (gimple stmt, tree addr, vo
   addr = get_base_address (addr);
   if (TREE_CODE (addr) == FUNCTION_DECL)
     {
-      struct cgraph_node *node = cgraph_node (addr);
+      struct cgraph_node *node = cgraph_get_create_node (addr);
       cgraph_mark_address_taken_node (node);
       ipa_record_reference ((struct cgraph_node *)data, NULL,
 			    node, NULL,
@@ -279,7 +279,7 @@ mark_load (gimple stmt, tree t, void *da
     {
       /* ??? 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_node (t);
+      struct cgraph_node *node = cgraph_get_create_node (t);
       cgraph_mark_address_taken_node (node);
       ipa_record_reference ((struct cgraph_node *)data, NULL,
 			    node, NULL,
@@ -334,7 +334,7 @@ static unsigned int
 build_cgraph_edges (void)
 {
   basic_block bb;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   struct pointer_set_t *visited_nodes = pointer_set_create ();
   gimple_stmt_iterator gsi;
   tree decl;
@@ -355,9 +355,8 @@ build_cgraph_edges (void)
 							 bb);
 	      decl = gimple_call_fndecl (stmt);
 	      if (decl)
-		cgraph_create_edge (node, cgraph_node (decl), stmt,
-				    bb->count, freq,
-				    bb->loop_depth);
+		cgraph_create_edge (node, cgraph_get_create_node (decl),
+				    stmt, bb->count, freq, bb->loop_depth);
 	      else
 		cgraph_create_indirect_edge (node, stmt,
 					     gimple_call_flags (stmt),
@@ -370,18 +369,18 @@ build_cgraph_edges (void)
 	      && gimple_omp_parallel_child_fn (stmt))
 	    {
 	      tree fn = gimple_omp_parallel_child_fn (stmt);
-	      ipa_record_reference (node, NULL, cgraph_node (fn),
+	      ipa_record_reference (node, NULL, cgraph_get_create_node (fn),
 				    NULL, 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, NULL, cgraph_node (fn),
+		ipa_record_reference (node, NULL, cgraph_get_create_node (fn),
 				      NULL, IPA_REF_ADDR, stmt);
 	      fn = gimple_omp_task_copy_fn (stmt);
 	      if (fn)
-		ipa_record_reference (node, NULL, cgraph_node (fn),
+		ipa_record_reference (node, NULL, cgraph_get_create_node (fn),
 				      NULL, IPA_REF_ADDR, stmt);
 	    }
 	}
@@ -445,7 +444,7 @@ unsigned int
 rebuild_cgraph_edges (void)
 {
   basic_block bb;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   gimple_stmt_iterator gsi;
 
   cgraph_node_remove_callees (node);
@@ -466,9 +465,8 @@ rebuild_cgraph_edges (void)
 							 bb);
 	      decl = gimple_call_fndecl (stmt);
 	      if (decl)
-		cgraph_create_edge (node, cgraph_node (decl), stmt,
-				    bb->count, freq,
-				    bb->loop_depth);
+		cgraph_create_edge (node, cgraph_get_create_node (decl), stmt,
+				    bb->count, freq, bb->loop_depth);
 	      else
 		cgraph_create_indirect_edge (node, stmt,
 					     gimple_call_flags (stmt),
@@ -496,7 +494,7 @@ void
 cgraph_rebuild_references (void)
 {
   basic_block bb;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   gimple_stmt_iterator gsi;
 
   ipa_remove_all_references (&node->ref_list);
@@ -543,7 +541,7 @@ struct gimple_opt_pass pass_rebuild_cgra
 static unsigned int
 remove_cgraph_callee_edges (void)
 {
-  cgraph_node_remove_callees (cgraph_node (current_function_decl));
+  cgraph_node_remove_callees (cgraph_get_node (current_function_decl));
   return 0;
 }
 
Index: src/gcc/cgraphunit.c
===================================================================
--- src.orig/gcc/cgraphunit.c	2011-03-19 01:31:22.000000000 +0100
+++ src/gcc/cgraphunit.c	2011-03-19 01:54:42.000000000 +0100
@@ -343,7 +343,7 @@ cgraph_lower_function (struct cgraph_nod
 void
 cgraph_finalize_function (tree decl, bool nested)
 {
-  struct cgraph_node *node = cgraph_node (decl);
+  struct cgraph_node *node = cgraph_get_create_node (decl);
 
   if (node->local.finalized)
     cgraph_reset_node (node);
@@ -390,7 +390,7 @@ cgraph_finalize_function (tree decl, boo
 void
 cgraph_mark_if_needed (tree decl)
 {
-  struct cgraph_node *node = cgraph_node (decl);
+  struct cgraph_node *node = cgraph_get_node (decl);
   if (node->local.finalized && cgraph_decide_is_function_needed (node, decl))
     cgraph_mark_needed_node (node);
 }
@@ -667,7 +667,7 @@ verify_cgraph_node (struct cgraph_node *
 				     && cgraph_get_node (decl)
 				     && (e->callee->former_clone_of
 					 != cgraph_get_node (decl)->decl)
-				     && !clone_of_p (cgraph_node (decl),
+				     && !clone_of_p (cgraph_get_node (decl),
 						     e->callee))
 			      {
 				error ("edge points to wrong declaration:");
@@ -995,10 +995,12 @@ cgraph_analyze_functions (void)
 
       /* If decl is a clone of an abstract function, mark that abstract
 	 function so that we don't release its body. The DECL_INITIAL() of that
-         abstract function declaration will be later needed to output debug info.  */
+	 abstract function declaration will be later needed to output debug
+	 info.  */
       if (DECL_ABSTRACT_ORIGIN (decl))
 	{
-	  struct cgraph_node *origin_node = cgraph_node (DECL_ABSTRACT_ORIGIN (decl));
+	  struct cgraph_node *origin_node;
+	  origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
 	  origin_node->abstract_and_needed = true;
 	}
 
@@ -1761,7 +1763,7 @@ cgraph_preserve_function_body_p (tree de
 
   gcc_assert (cgraph_global_info_ready);
   /* Look if there is any clone around.  */
-  node = cgraph_node (decl);
+  node = cgraph_get_node (decl);
   if (node->clones)
     return true;
   return false;
@@ -1983,7 +1985,7 @@ cgraph_copy_node_for_versioning (struct
 
    gcc_assert (old_version);
 
-   new_version = cgraph_node (new_decl);
+   new_version = cgraph_create_node (new_decl);
 
    new_version->analyzed = true;
    new_version->local = old_version->local;
@@ -2101,7 +2103,7 @@ save_inline_function_body (struct cgraph
 {
   struct cgraph_node *first_clone, *n;
 
-  gcc_assert (node == cgraph_node (node->decl));
+  gcc_assert (node == cgraph_get_node (node->decl));
 
   cgraph_lower_function (node);
 
@@ -2109,7 +2111,7 @@ save_inline_function_body (struct cgraph
 
   first_clone->decl = copy_node (node->decl);
   cgraph_insert_node_to_hashtable (first_clone);
-  gcc_assert (first_clone == cgraph_node (first_clone->decl));
+  gcc_assert (first_clone == cgraph_get_node (first_clone->decl));
   if (first_clone->next_sibling_clone)
     {
       for (n = first_clone->next_sibling_clone; n->next_sibling_clone; n = n->next_sibling_clone)
Index: src/gcc/config/i386/i386.c
===================================================================
--- src.orig/gcc/config/i386/i386.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/config/i386/i386.c	2011-03-19 01:54:42.000000000 +0100
@@ -9229,7 +9229,7 @@ ix86_compute_frame_layout (struct ix86_f
            && cfun->machine->use_fast_prologue_epilogue_nregs != frame->nregs)
     {
       int count = frame->nregs;
-      struct cgraph_node *node = cgraph_node (current_function_decl);
+      struct cgraph_node *node = cgraph_get_node (current_function_decl);
 
       cfun->machine->use_fast_prologue_epilogue_nregs = count;
 
Index: src/gcc/cp/class.c
===================================================================
--- src.orig/gcc/cp/class.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/cp/class.c	2011-03-19 01:54:42.000000000 +0100
@@ -8405,7 +8405,7 @@ cp_fold_obj_type_ref (tree ref, tree kno
 				  DECL_VINDEX (fndecl)));
 #endif
 
-  cgraph_node (fndecl)->local.vtable_method = true;
+  cgraph_get_create_node (fndecl)->local.vtable_method = true;
 
   return build_address (fndecl);
 }
Index: src/gcc/cp/decl2.c
===================================================================
--- src.orig/gcc/cp/decl2.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/cp/decl2.c	2011-03-19 01:54:42.000000000 +0100
@@ -3374,11 +3374,13 @@ cxx_callgraph_analyze_expr (tree *tp, in
     {
     case PTRMEM_CST:
       if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
-	cgraph_mark_address_taken_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
+	cgraph_mark_address_taken_node (
+			      cgraph_get_create_node (PTRMEM_CST_MEMBER (t)));
       break;
     case BASELINK:
       if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
-	cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
+	cgraph_mark_address_taken_node (
+			      cgraph_get_create_node (BASELINK_FUNCTIONS (t)));
       break;
     case VAR_DECL:
       if (DECL_CONTEXT (t)
@@ -3891,7 +3893,7 @@ cp_write_global_declarations (void)
 	  if (!DECL_EXTERNAL (decl)
 	      && decl_needed_p (decl)
 	      && !TREE_ASM_WRITTEN (decl)
-	      && !cgraph_node (decl)->local.finalized)
+	      && !cgraph_get_create_node (decl)->local.finalized)
 	    {
 	      /* We will output the function; no longer consider it in this
 		 loop.  */
Index: src/gcc/cp/optimize.c
===================================================================
--- src.orig/gcc/cp/optimize.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/cp/optimize.c	2011-03-19 01:54:42.000000000 +0100
@@ -309,7 +309,8 @@ maybe_clone_body (tree fn)
 	  && (!DECL_ONE_ONLY (fns[0])
 	      || (HAVE_COMDAT_GROUP
 		  && DECL_WEAK (fns[0])))
-	  && cgraph_same_body_alias (cgraph_node (fns[0]), clone, fns[0]))
+	  && cgraph_same_body_alias (cgraph_get_create_node (fns[0]), clone,
+				     fns[0]))
 	{
 	  alias = true;
 	  if (DECL_ONE_ONLY (fns[0]))
@@ -423,8 +424,8 @@ maybe_clone_body (tree fn)
 	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
 	     virtual, it goes into the same comdat group as well.  */
 	  DECL_COMDAT_GROUP (fns[2]) = comdat_group;
-	  base_dtor_node = cgraph_node (fns[0]);
-	  deleting_dtor_node = cgraph_node (fns[2]);
+	  base_dtor_node = cgraph_get_create_node (fns[0]);
+	  deleting_dtor_node = cgraph_get_create_node (fns[2]);
 	  gcc_assert (base_dtor_node->same_comdat_group == NULL);
 	  gcc_assert (deleting_dtor_node->same_comdat_group == NULL);
 	  base_dtor_node->same_comdat_group = deleting_dtor_node;
Index: src/gcc/cp/semantics.c
===================================================================
--- src.orig/gcc/cp/semantics.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/cp/semantics.c	2011-03-19 01:54:42.000000000 +0100
@@ -8352,8 +8352,8 @@ maybe_add_lambda_conv_op (tree type)
       /* Put the thunk in the same comdat group as the call op.  */
       struct cgraph_node *callop_node, *thunk_node;
       DECL_COMDAT_GROUP (statfn) = DECL_COMDAT_GROUP (callop);
-      callop_node = cgraph_node (callop);
-      thunk_node = cgraph_node (statfn);
+      callop_node = cgraph_get_create_node (callop);
+      thunk_node = cgraph_get_create_node (statfn);
       gcc_assert (callop_node->same_comdat_group == NULL);
       gcc_assert (thunk_node->same_comdat_group == NULL);
       callop_node->same_comdat_group = thunk_node;
Index: src/gcc/ipa.c
===================================================================
--- src.orig/gcc/ipa.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/ipa.c	2011-03-19 01:54:42.000000000 +0100
@@ -1626,7 +1626,7 @@ record_cdtor_fn (struct cgraph_node *nod
     VEC_safe_push (tree, heap, static_ctors, node->decl);
   if (DECL_STATIC_DESTRUCTOR (node->decl))
     VEC_safe_push (tree, heap, static_dtors, node->decl);
-  node = cgraph_node (node->decl);
+  node = cgraph_get_node (node->decl);
   node->local.disregard_inline_limits = 1;
 }
 
Index: src/gcc/ipa-inline.c
===================================================================
--- src.orig/gcc/ipa-inline.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/ipa-inline.c	2011-03-19 01:54:42.000000000 +0100
@@ -1739,7 +1739,7 @@ static GTY ((length ("nnodes"))) struct
 static unsigned int
 cgraph_early_inlining (void)
 {
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
   unsigned int todo = 0;
   int iterations = 0;
 
@@ -2021,7 +2021,7 @@ compute_inline_parameters (struct cgraph
 static unsigned int
 compute_inline_parameters_for_current (void)
 {
-  compute_inline_parameters (cgraph_node (current_function_decl));
+  compute_inline_parameters (cgraph_get_node (current_function_decl));
   return 0;
 }
 
Index: src/gcc/ipa-prop.c
===================================================================
--- src.orig/gcc/ipa-prop.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/ipa-prop.c	2011-03-19 01:54:42.000000000 +0100
@@ -1645,7 +1645,7 @@ ipa_make_edge_direct_to_target (struct c
     target = TREE_OPERAND (target, 0);
   if (TREE_CODE (target) != FUNCTION_DECL)
     return NULL;
-  callee = cgraph_node (target);
+  callee = cgraph_get_node (target);
   if (!callee)
     return NULL;
   ipa_check_create_node_params ();
Index: src/gcc/ipa-pure-const.c
===================================================================
--- src.orig/gcc/ipa-pure-const.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/ipa-pure-const.c	2011-03-19 01:54:42.000000000 +0100
@@ -1563,7 +1563,7 @@ local_pure_const (void)
   bool skip;
   struct cgraph_node *node;
 
-  node = cgraph_node (current_function_decl);
+  node = cgraph_get_node (current_function_decl);
   skip = skip_function_for_local_pure_const (node);
   if (!warn_suggest_attribute_const
       && !warn_suggest_attribute_pure
Index: src/gcc/ipa-split.c
===================================================================
--- src.orig/gcc/ipa-split.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/ipa-split.c	2011-03-19 01:54:42.000000000 +0100
@@ -1057,7 +1057,7 @@ split_function (struct split_point *spli
 
   /* Now create the actual clone.  */
   rebuild_cgraph_edges ();
-  node = cgraph_function_versioning (cgraph_node (current_function_decl),
+  node = cgraph_function_versioning (cgraph_get_node (current_function_decl),
 				     NULL, NULL,
 				     args_to_skip,
 				     split_point->split_bbs,
@@ -1070,7 +1070,7 @@ split_function (struct split_point *spli
       DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
       DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
     }
-  cgraph_node_remove_callees (cgraph_node (current_function_decl));
+  cgraph_node_remove_callees (cgraph_get_node (current_function_decl));
   if (!split_part_return_p)
     TREE_THIS_VOLATILE (node->decl) = 1;
   if (dump_file)
@@ -1242,7 +1242,7 @@ execute_split_functions (void)
   basic_block bb;
   int overall_time = 0, overall_size = 0;
   int todo = 0;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
 
   if (flags_from_decl_or_type (current_function_decl) & ECF_NORETURN)
     {
Index: src/gcc/ipa-struct-reorg.c
===================================================================
--- src.orig/gcc/ipa-struct-reorg.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/ipa-struct-reorg.c	2011-03-19 01:54:42.000000000 +0100
@@ -1735,8 +1735,8 @@ update_cgraph_with_malloc_call (gimple m
 
   malloc_fn_decl = gimple_call_fndecl (malloc_stmt);
 
-  src = cgraph_node (context);
-  dest = cgraph_node (malloc_fn_decl);
+  src = cgraph_do_get_node (context);
+  dest = cgraph_do_get_node (malloc_fn_decl);
   cgraph_create_edge (src, dest, malloc_stmt,
 		      gimple_bb (malloc_stmt)->count,
 		      compute_call_stmt_bb_frequency
Index: src/gcc/ipa-type-escape.c
===================================================================
--- src.orig/gcc/ipa-type-escape.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/ipa-type-escape.c	2011-03-19 01:54:42.000000000 +0100
@@ -1328,7 +1328,7 @@ check_call (gimple call)
     {
       tree arg_type;
       tree last_arg_type = NULL;
-      callee = cgraph_node(callee_t);
+      callee = cgraph_do_get_node(callee_t);
       avail = cgraph_function_body_availability (callee);
 
       /* Check that there are no implicit casts in the passing of
Index: src/gcc/matrix-reorg.c
===================================================================
--- src.orig/gcc/matrix-reorg.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/matrix-reorg.c	2011-03-19 01:54:42.000000000 +0100
@@ -2169,7 +2169,7 @@ transform_allocation_sites (void **slot,
   update_ssa (TODO_update_ssa);
   /* Replace the malloc size argument in the malloc of level 0 to be
      the size of all the dimensions.  */
-  c_node = cgraph_node (mi->allocation_function_decl);
+  c_node = cgraph_do_get_node (mi->allocation_function_decl);
   old_size_0 = gimple_call_arg (call_stmt_0, 0);
   tmp = force_gimple_operand_gsi (&gsi, mi->dimension_size[0], true,
 				  NULL, true, GSI_SAME_STMT);
@@ -2218,7 +2218,7 @@ transform_allocation_sites (void **slot,
       if (!mi->free_stmts[i].stmt)
 	continue;
 
-      c_node = cgraph_node (mi->free_stmts[i].func);
+      c_node = cgraph_do_get_node (mi->free_stmts[i].func);
       gcc_assert (is_gimple_call (mi->free_stmts[i].stmt));
       e = cgraph_edge (c_node, mi->free_stmts[i].stmt);
       gcc_assert (e);
Index: src/gcc/tree-inline.c
===================================================================
--- src.orig/gcc/tree-inline.c	2011-03-19 01:31:22.000000000 +0100
+++ src/gcc/tree-inline.c	2011-03-19 01:54:42.000000000 +0100
@@ -1727,7 +1727,7 @@ copy_bb (copy_body_data *id, basic_block
 		       && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
 		  && (fn = gimple_call_fndecl (stmt)) != NULL)
 		{
-		  struct cgraph_node *dest = cgraph_node (fn);
+		  struct cgraph_node *dest = cgraph_get_node (fn);
 
 		  /* We have missing edge in the callgraph.  This can happen
 		     when previous inlining turned an indirect call into a
@@ -3473,13 +3473,14 @@ estimate_num_insns (gimple stmt, eni_wei
 	tree addr = gimple_call_fn (stmt);
 	tree funtype = TREE_TYPE (addr);
 	bool stdarg = false;
+	struct cgraph_node *node;
 
 	if (POINTER_TYPE_P (funtype))
 	  funtype = TREE_TYPE (funtype);
 
 	/* Do not special case builtins where we see the body.
 	   This just confuse inliner.  */
-	if (!decl || cgraph_node (decl)->analyzed)
+	if (!decl || !(node = cgraph_get_node (decl)) || node->analyzed)
 	  ;
 	/* For buitins that are likely expanded to nothing or
 	   inlined do not account operand costs.  */
@@ -4197,7 +4198,7 @@ optimize_inline_calls (tree fn)
   /* Clear out ID.  */
   memset (&id, 0, sizeof (id));
 
-  id.src_node = id.dst_node = cgraph_node (fn);
+  id.src_node = id.dst_node = cgraph_get_node (fn);
   gcc_assert (id.dst_node->analyzed);
   id.dst_fn = fn;
   /* Or any functions that aren't finished yet.  */
@@ -5041,8 +5042,8 @@ tree_function_versioning (tree old_decl,
 	      && TREE_CODE (new_decl) == FUNCTION_DECL);
   DECL_POSSIBLY_INLINED (old_decl) = 1;
 
-  old_version_node = cgraph_node (old_decl);
-  new_version_node = cgraph_node (new_decl);
+  old_version_node = cgraph_do_get_node (old_decl);
+  new_version_node = cgraph_do_get_node (new_decl);
 
   /* Output the inlining info for this abstract function, since it has been
      inlined.  If we don't do this now, we can lose the information about the
Index: src/gcc/varasm.c
===================================================================
--- src.orig/gcc/varasm.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/varasm.c	2011-03-19 01:54:42.000000000 +0100
@@ -605,11 +605,14 @@ function_section_1 (tree decl, bool forc
 
   if (decl)
     {
-      struct cgraph_node *node = cgraph_node (decl);
+      struct cgraph_node *node = cgraph_get_node (decl);
 
-      freq = node->frequency;
-      startup = node->only_called_at_startup;
-      exit = node->only_called_at_exit;
+      if (node)
+	{
+	  freq = node->frequency;
+	  startup = node->only_called_at_startup;
+	  exit = node->only_called_at_exit;
+	}
     }
   if (force_cold)
     freq = NODE_FREQUENCY_UNLIKELY_EXECUTED;
@@ -1607,11 +1610,12 @@ assemble_start_function (tree decl, cons
     }
   else if (DECL_SECTION_NAME (decl))
     {
+      struct cgraph_node *node = cgraph_get_node (current_function_decl);
       /* Calls to function_section rely on first_function_block_is_cold
 	 being accurate.  */
-      first_function_block_is_cold
-	 = (cgraph_node (current_function_decl)->frequency
-	    == NODE_FREQUENCY_UNLIKELY_EXECUTED);
+      first_function_block_is_cold = (node
+				      && node->frequency
+				      == NODE_FREQUENCY_UNLIKELY_EXECUTED);
     }
 
   in_cold_section_p = first_function_block_is_cold;
@@ -2230,7 +2234,7 @@ mark_decl_referenced (tree decl)
 	 If we know a method will be emitted in other TU and no new
 	 functions can be marked reachable, just use the external
 	 definition.  */
-      struct cgraph_node *node = cgraph_node (decl);
+      struct cgraph_node *node = cgraph_get_create_node (decl);
       if (!DECL_EXTERNAL (decl)
 	  && (!node->local.vtable_method || !cgraph_global_info_ready
 	      || !node->local.finalized))
@@ -5838,7 +5842,7 @@ assemble_alias (tree decl, tree target)
 
   /* Allow aliases to aliases.  */
   if (TREE_CODE (decl) == FUNCTION_DECL)
-    cgraph_node (decl)->alias = true;
+    cgraph_get_create_node (decl)->alias = true;
   else
     varpool_node (decl)->alias = true;
 
Index: src/gcc/ada/gcc-interface/utils.c
===================================================================
--- src.orig/gcc/ada/gcc-interface/utils.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/ada/gcc-interface/utils.c	2011-03-19 01:54:42.000000000 +0100
@@ -1898,7 +1898,7 @@ end_subprog_body (tree body)
   else
     /* Register this function with cgraph just far enough to get it
        added to our parent's nested function list.  */
-    (void) cgraph_node (fndecl);
+    (void) cgraph_get_create_node (fndecl);
 }
 
 tree
Index: src/gcc/fortran/trans-decl.c
===================================================================
--- src.orig/gcc/fortran/trans-decl.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/fortran/trans-decl.c	2011-03-19 01:54:42.000000000 +0100
@@ -4924,7 +4924,7 @@ gfc_generate_function_code (gfc_namespac
   if (decl_function_context (fndecl))
     /* Register this function with cgraph just far enough to get it
        added to our parent's nested function list.  */
-    (void) cgraph_node (fndecl);
+    (void) cgraph_get_create_node (fndecl);
   else
     cgraph_finalize_function (fndecl, true);
 
Index: src/gcc/java/decl.c
===================================================================
--- src.orig/gcc/java/decl.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/java/decl.c	2011-03-19 01:54:42.000000000 +0100
@@ -1928,7 +1928,10 @@ java_mark_decl_local (tree decl)
 #ifdef ENABLE_CHECKING
   /* Double check that we didn't pass the function to the callgraph early.  */
   if (TREE_CODE (decl) == FUNCTION_DECL)
-    gcc_assert (!cgraph_node (decl)->local.finalized);
+    {
+      struct cgraph_node *node = cgraph_get_node (decl);
+      gcc_assert (!node || !node->local.finalized);
+    }
 #endif
   gcc_assert (!DECL_RTL_SET_P (decl));
 }
Index: src/gcc/objc/objc-act.c
===================================================================
--- src.orig/gcc/objc/objc-act.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/objc/objc-act.c	2011-03-19 01:54:42.000000000 +0100
@@ -4519,14 +4519,16 @@ mark_referenced_methods (void)
       chain = CLASS_CLS_METHODS (impent->imp_context);
       while (chain)
 	{
-	  cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
+	  cgraph_mark_needed_node (
+			   cgraph_get_create_node (METHOD_DEFINITION (chain)));
 	  chain = DECL_CHAIN (chain);
 	}
 
       chain = CLASS_NST_METHODS (impent->imp_context);
       while (chain)
 	{
-	  cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)));
+	  cgraph_mark_needed_node (
+			   cgraph_get_create_node (METHOD_DEFINITION (chain)));
 	  chain = DECL_CHAIN (chain);
 	}
     }
Index: src/gcc/cp/mangle.c
===================================================================
--- src.orig/gcc/cp/mangle.c	2011-03-19 01:16:24.000000000 +0100
+++ src/gcc/cp/mangle.c	2011-03-19 01:54:42.000000000 +0100
@@ -3170,7 +3170,7 @@ mangle_decl (const tree decl)
       if (vague_linkage_p (decl))
 	DECL_WEAK (alias) = 1;
       if (TREE_CODE (decl) == FUNCTION_DECL)
-	cgraph_same_body_alias (cgraph_node (decl), alias, decl);
+	cgraph_same_body_alias (cgraph_get_create_node (decl), alias, decl);
       else
 	varpool_extra_name_alias (alias, decl);
 #endif
Index: src/gcc/cp/method.c
===================================================================
--- src.orig/gcc/cp/method.c	2011-03-19 01:16:23.000000000 +0100
+++ src/gcc/cp/method.c	2011-03-19 01:54:42.000000000 +0100
@@ -259,8 +259,9 @@ make_alias_for_thunk (tree function)
 
   if (!flag_syntax_only)
     {
-      struct cgraph_node *aliasn = cgraph_same_body_alias (cgraph_node (function),
-							   alias, function);
+      struct cgraph_node *aliasn;
+      aliasn = cgraph_same_body_alias (cgraph_get_create_node (function),
+				       alias, function);
       DECL_ASSEMBLER_NAME (function);
       gcc_assert (aliasn != NULL);
     }
@@ -378,7 +379,7 @@ use_thunk (tree thunk_fndecl, bool emit_
   a = nreverse (t);
   DECL_ARGUMENTS (thunk_fndecl) = a;
   TREE_ASM_WRITTEN (thunk_fndecl) = 1;
-  cgraph_add_thunk (cgraph_node (function), thunk_fndecl, function,
+  cgraph_add_thunk (cgraph_get_create_node (function), thunk_fndecl, function,
 		    this_adjusting, fixed_offset, virtual_value,
 		    virtual_offset, alias);
 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 2/4] Tweaks to C++ -> call graph interface
  2011-03-19 19:29 [PATCH 0/4] Remove (lots of) lazy call graph node construction Martin Jambor
  2011-03-19 19:30 ` [PATCH 4/4] Tweaks to objc -> call graph interface Martin Jambor
@ 2011-03-19 19:30 ` Martin Jambor
  2011-03-23 16:55   ` Jan Hubicka
  2011-03-19 19:30 ` [PATCH 1/4] Remove cgraph_node function and fixup all callers Martin Jambor
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Martin Jambor @ 2011-03-19 19:30 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jan Hubicka

[-- Attachment #1: cgraph_cp_calls.diff --]
[-- Type: text/plain, Size: 4982 bytes --]

I concede that my understanding of the C++ front-end inner workings
are quite narrow and so the folling is basically a suggestion.  But it
seems to me that at a few places where C++ queries the call graph for
a node, the lazy node creation is not necessary.  If a maintainer can
verify and approve (parts of) this after the big patch is committed,
it would be a nice cleanup too.

Thanks,

Martin


2011-03-18  Martin Jambor  <mjambor@suse.cz>

cp/
	* class.c (cp_fold_obj_type_ref): Call cgraph_get_node instead of
	cgraph_get_create_node.
	* decl2.c (cxx_callgraph_analyze_expr): Call cgraph_do_get_node
	instead of cgraph_get_create_node.
	(cp_write_global_declarations): Call cgraph_get_node instead of
	cgraph_get_create_node.
	* method.c (make_alias_for_thunk): Call cgraph_do_get_node instead
	of cgraph_get_create_node.
	(use_thunk): Likewise.
	* optimize.c (maybe_clone_body): Call cgraph_same_body_alias only
	when flag_syntax_only is not set.  Call cgraph_do_get_node instead of
	cgraph_get_create_node.
	(maybe_clone_body): Call cgraph_get_node instead of
	cgraph_get_create_node.

Index: src/gcc/cp/class.c
===================================================================
--- src.orig/gcc/cp/class.c	2011-03-18 19:34:07.000000000 +0100
+++ src/gcc/cp/class.c	2011-03-18 19:34:38.000000000 +0100
@@ -8405,7 +8405,7 @@ cp_fold_obj_type_ref (tree ref, tree kno
 				  DECL_VINDEX (fndecl)));
 #endif
 
-  cgraph_get_create_node (fndecl)->local.vtable_method = true;
+  cgraph_get_node (fndecl)->local.vtable_method = true;
 
   return build_address (fndecl);
 }
Index: src/gcc/cp/decl2.c
===================================================================
--- src.orig/gcc/cp/decl2.c	2011-03-18 19:34:07.000000000 +0100
+++ src/gcc/cp/decl2.c	2011-03-18 19:34:39.000000000 +0100
@@ -3375,12 +3375,12 @@ cxx_callgraph_analyze_expr (tree *tp, in
     case PTRMEM_CST:
       if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
 	cgraph_mark_address_taken_node (
-			      cgraph_get_create_node (PTRMEM_CST_MEMBER (t)));
+				  cgraph_do_get_node (PTRMEM_CST_MEMBER (t)));
       break;
     case BASELINK:
       if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
 	cgraph_mark_address_taken_node (
-			      cgraph_get_create_node (BASELINK_FUNCTIONS (t)));
+				  cgraph_do_get_node (BASELINK_FUNCTIONS (t)));
       break;
     case VAR_DECL:
       if (DECL_CONTEXT (t)
@@ -3893,7 +3893,7 @@ cp_write_global_declarations (void)
 	  if (!DECL_EXTERNAL (decl)
 	      && decl_needed_p (decl)
 	      && !TREE_ASM_WRITTEN (decl)
-	      && !cgraph_get_create_node (decl)->local.finalized)
+	      && !cgraph_get_node (decl)->local.finalized)
 	    {
 	      /* We will output the function; no longer consider it in this
 		 loop.  */
Index: src/gcc/cp/method.c
===================================================================
--- src.orig/gcc/cp/method.c	2011-03-18 19:34:07.000000000 +0100
+++ src/gcc/cp/method.c	2011-03-18 19:34:40.000000000 +0100
@@ -260,7 +260,7 @@ make_alias_for_thunk (tree function)
   if (!flag_syntax_only)
     {
       struct cgraph_node *aliasn;
-      aliasn = cgraph_same_body_alias (cgraph_get_create_node (function),
+      aliasn = cgraph_same_body_alias (cgraph_do_get_node (function),
 				       alias, function);
       DECL_ASSEMBLER_NAME (function);
       gcc_assert (aliasn != NULL);
@@ -379,7 +379,7 @@ use_thunk (tree thunk_fndecl, bool emit_
   a = nreverse (t);
   DECL_ARGUMENTS (thunk_fndecl) = a;
   TREE_ASM_WRITTEN (thunk_fndecl) = 1;
-  cgraph_add_thunk (cgraph_get_create_node (function), thunk_fndecl, function,
+  cgraph_add_thunk (cgraph_do_get_node (function), thunk_fndecl, function,
 		    this_adjusting, fixed_offset, virtual_value,
 		    virtual_offset, alias);
 
Index: src/gcc/cp/optimize.c
===================================================================
--- src.orig/gcc/cp/optimize.c	2011-03-18 19:34:07.000000000 +0100
+++ src/gcc/cp/optimize.c	2011-03-18 19:34:40.000000000 +0100
@@ -309,8 +309,9 @@ maybe_clone_body (tree fn)
 	  && (!DECL_ONE_ONLY (fns[0])
 	      || (HAVE_COMDAT_GROUP
 		  && DECL_WEAK (fns[0])))
-	  && cgraph_same_body_alias (cgraph_get_create_node (fns[0]), clone,
-				     fns[0]))
+	  && (flag_syntax_only
+	      || cgraph_same_body_alias (cgraph_do_get_node (fns[0]), clone,
+					 fns[0])))
 	{
 	  alias = true;
 	  if (DECL_ONE_ONLY (fns[0]))
@@ -424,8 +425,8 @@ maybe_clone_body (tree fn)
 	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
 	     virtual, it goes into the same comdat group as well.  */
 	  DECL_COMDAT_GROUP (fns[2]) = comdat_group;
-	  base_dtor_node = cgraph_get_create_node (fns[0]);
-	  deleting_dtor_node = cgraph_get_create_node (fns[2]);
+	  base_dtor_node = cgraph_get_node (fns[0]);
+	  deleting_dtor_node = cgraph_get_node (fns[2]);
 	  gcc_assert (base_dtor_node->same_comdat_group == NULL);
 	  gcc_assert (deleting_dtor_node->same_comdat_group == NULL);
 	  base_dtor_node->same_comdat_group = deleting_dtor_node;

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/4] Remove (lots of) lazy call graph node construction
  2011-03-19 19:29 [PATCH 0/4] Remove (lots of) lazy call graph node construction Martin Jambor
                   ` (3 preceding siblings ...)
  2011-03-19 19:30 ` [PATCH 3/4] A tweak to fortran -> call graph interface Martin Jambor
@ 2011-03-23  8:53 ` Jan Hubicka
  4 siblings, 0 replies; 13+ messages in thread
From: Jan Hubicka @ 2011-03-23  8:53 UTC (permalink / raw)
  To: Martin Jambor; +Cc: GCC Patches, Jan Hubicka

> Hi,
> 
> I believe the general consensus is that lazy call graph node creation
> is no longer a good idea and a few of us have seen bugs caused by a
> creation of a node when we did not expect it.  Therefore I embarked on
> getting rid of it.  In the process I quickly realized it would be
> difficult to do that completely but it is certainly possible to weed
> it out of most places where it is not necessary.  We can then tackle
> the remaining places separately.
> 
> These patches are meant to be applied on top of
> http://gcc.gnu.org/ml/gcc-patches/2011-03/msg01170.html
> 
> The first patch in the series removes the cgraph_node function.  Most
> of its callers should use already existing cgraph_get_node instead,
> for the others there are new functions:
> 
> - craph_create_node will create a node but fail on assert if there
>   already is a node for the declaration
> 
> - cgraph_get_create_node is the new lazy node creation.  I did not
>   want to continue using cgraph_node name because I really thought the
>   it was unfortunate and the new name will also help us to discourage
>   potential new uses and isolate those that we might want to convert
>   to a non-lazy way of creating nodes later.
> 
> - cgraph_do_get_node is a simple wrapper around cgraph_get_node which
>   checking_asserts that the return value is not NULL.  I found it very
>   useful while developing the patch and think it can be sometimes
>   useful even in the longer term, for example when the result is
>   stored in some data structure which is to be used later.  If the
>   general consensus is that we don't want it, it is easy to remove it
>   from the patch.

Well, I didn't quite expected we will get 3 new accesstors to the cgraph,
but I see it can be useful.  I would perhaps go with cgraph_maybe_create_node
that seems more consistent with names elsewhere, but cgraph_get_create_node
seems OK to me, too.

Thanks!
Honza

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/4] Remove cgraph_node function and fixup all callers
  2011-03-19 19:30 ` [PATCH 1/4] Remove cgraph_node function and fixup all callers Martin Jambor
@ 2011-03-23  9:09   ` Jan Hubicka
  2011-03-25 10:25     ` Martin Jambor
  0 siblings, 1 reply; 13+ messages in thread
From: Jan Hubicka @ 2011-03-23  9:09 UTC (permalink / raw)
  To: Martin Jambor; +Cc: GCC Patches, Jan Hubicka

> 2011-03-18  Martin Jambor  <mjambor@suse.cz>
> 
> 	* cgraph.h (cgraph_node): Remove function declaration.
> 	(cgraph_create_node): Declare.
> 	(cgraph_get_create_node): Likewise.
> 	(cgraph_do_get_node): New function.
> 
> 	* cgraph.c (cgraph_create_node): Renamed to cgraph_create_node_1.
> 	Updated all callers.
> 	(cgraph_node): Renamed to cgraph_create_node, assert that a node for
> 	the decl does not already exist.  Call cgraph_get_create_node instead
> 	of cgraph_node.
> 	(cgraph_get_create_node): New function.
> 	(cgraph_same_body_alias): Update comment.
> 	(cgraph_set_call_stmt): Call cgraph_do_get_node instead of cgraph_node.
> 	(cgraph_update_edges_for_call_stmt): Likewise.
> 	(cgraph_clone_edge): Likewise.
> 	(cgraph_create_virtual_clone): Likewise.
> 	(cgraph_set_call_stmt): Call cgraph_get_create_node instead of
> 	cgraph_node.
> 	(cgraph_local_info): Call cgraph_get_node instead of cgraph_node,
> 	handle NULL return value.
> 	(cgraph_global_info): Likewise.
> 	(cgraph_rtl_info): Likewise.
> 	(cgraph_add_new_function): Call cgraph_create_node or
> 	cgraph_get_create_node instead of cgraph_node.
> 
> 	* cgraphbuild.c (record_reference): Call cgraph_get_create_node
> 	instead of cgraph_node.
> 	(record_eh_tables): Likewise.
> 	(mark_address): Likewise.
> 	(mark_load): Likewise.
> 	(build_cgraph_edges): Call cgraph_get_node and cgraph_get_create_node
> 	instead of cgraph_node.
> 	(rebuild_cgraph_edges): Likewise.
> 	(cgraph_rebuild_references): Call cgraph_get_node instead of
> 	cgraph_node.
> 	(remove_cgraph_callee_edges): Likewise.
> 
> 	* cgraphunit.c (cgraph_finalize_function): Call cgraph_get_create_node
> 	instead of cgraph_node.
> 	(cgraph_mark_if_needed): Call cgraph_get_node instead of cgraph_node.
> 	(verify_cgraph_node): Likewise.
> 	(cgraph_analyze_functions): Likewise.
> 	(cgraph_preserve_function_body_p): Likewise.
> 	(save_inline_function_body): Likewise.
> 	(save_inline_function_body): Likewise.
> 	(cgraph_copy_node_for_versioning): Call cgraph_create_node instead of
> 	cgraph_node.
> 
> 	* tree-inline.c (copy_bb): Call cgraph_get_node instead of cgraph_node.
> 	(estimate_num_insns): Likewise and handle returned NULL.
> 	(optimize_inline_calls): Call cgraph_get_node instead of cgraph_node.
> 	(tree_function_versioning): Call cgraph_do_get_node instead of
> 	cgraph_node.
> 
> 	* lto-symtab.c (lto_symtab_merge_cgraph_nodes_1): Call
> 	cgraph_create_node instead of cgraph_node.
> 
> 	* c-decl.c (finish_function): Call cgraph_get_create_node instead
> 	of cgraph_node.
> 	* c-family/c-gimplify.c (c_genericize): Likewise.
> 	* lto-cgraph.c (input_node): Likewise.
> 	* lto-streamer-in.c (input_function): Likewise.
> 
> 	* except.c (set_nothrow_function_flags): Call cgraph_get_node instead
> 	of cgraph_node.
> 	* final.c (rest_of_clean_state): Likewise.
> 	* gimple-iterator.c (update_call_edge_frequencies): Likewise.
> 	* passes.c (pass_init_dump_file): Likewise.
> 	(execute_all_ipa_transforms): Likewise.
> 	(function_called_by_processed_nodes_p): Likewise.
> 	* predict.c (maybe_hot_frequency_p): Likewise.
> 	(probably_never_executed_bb_p): Likewise.
> 	(compute_function_frequency): Likewise.
> 	* tree-nested.c (check_for_nested_with_variably_modified): Likewise.
> 	(unnest_nesting_tree_1): Likewise.
> 	(lower_nested_functions): Likewise.
> 	* tree-optimize.c (execute_fixup_cfg): Likewise.
> 	(tree_rest_of_compilation): Likewise.
> 	* tree-optimize.c (execute_fixup_cfg): Likewise.
> 	(tree_rest_of_compilation): Likewise.
> 	* tree-profile.c (gimple_gen_ic_func_profiler): Likewise.
> 	* tree-sra.c (ipa_early_sra): Likewise.
> 	* tree-ssa-loop-ivopts.c (computation_cost): Likewise.
> 	* config/i386/i386.c (ix86_compute_frame_layout): Likewise.
> 	* ipa.c (record_cdtor_fn): Likewise.
> 	* ipa-inline.c (cgraph_early_inlining): Likewise.
> 	(compute_inline_parameters_for_current): Likewise.
> 	* ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
> 	* ipa-pure-const.c (local_pure_const): Likewise.
> 	* ipa-split.c (split_function): Likewise.
> 	(split_function): Likewise.
> 	(execute_split_functions): Likewise.
> 
> 	* lto-streamer-in.c (lto_read_body): Call cgraph_do_get_node instead
> 	of cgraph_node.
> 	* omp-low.c (new_omp_context): Likewise.
> 	(create_task_copyfn): Likewise.
> 	* tree-emutls.c (lower_emutls_function_body): Likewise.
> 	* ipa-struct-reorg.c (update_cgraph_with_malloc_call): Likewise.
> 	* ipa-type-escape.c (check_call): Likewise.
> 	* matrix-reorg.c (transform_allocation_sites): Likewise.
> 
> 	* gimplify.c (unshare_body): Call cgraph_get_node instead of
> 	cgraph_node, handle NULL return value.
> 	(unvisit_body): Likewise.
> 	(gimplify_body): Likewise.
> 	* predict.c (optimize_function_for_size_p): Likewise.
> 	* tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Likewise.
> 	(call_may_clobber_ref_p_1): Likewise.
> 
> 	* varasm.c (function_section_1): Call cgraph_get_node instead of
> 	cgraph_node and handle returned NULL.
> 	(assemble_start_function): Likewise.
> 	(mark_decl_referenced): Call cgraph_get_create_node instead of
> 	cgraph_node.
> 	(assemble_alias): Likewise.
> 
> gcc/c-family/
> 	* c-gimplify.c (c_genericize): Call cgraph_get_create_node instead
> 
> gcc/cp/
> 	* cp/class.c (cp_fold_obj_type_ref): Call cgraph_get_create_node
> 	instead of cgraph_node.
> 	* cp/decl2.c (cxx_callgraph_analyze_expr): Likewise.
> 	(cp_write_global_declarations): Likewise.
> 	* cp/optimize.c (maybe_clone_body): Likewise.
> 	(maybe_clone_body): Likewise.
> 	* cp/semantics.c (maybe_add_lambda_conv_op): Likewise.
> 	* cp/mangle.c (mangle_decl): Likewise.
> 	* cp/method.c (make_alias_for_thunk): Likewise.
> 	(use_thunk): Likewise.
> 
> gcc/ada/
> 	* gcc-interface/utils.c (end_subprog_body): Call
> 	cgraph_get_create_node instead of cgraph_node.
> 
> gcc/fortran/
> 	* trans-decl.c (gfc_generate_function_code): Call
> 	cgraph_get_create_node instead of cgraph_node.
> 
> gcc/java/
> 	* decl.c (java_mark_decl_local): Call cgraph_get_node instead of
> 	cgraph_node and handle returned NULL.
> 
> gcc/objc/
> 	* objc-act.c (mark_referenced_methods): Call cgraph_get_create_node
> 	instead of cgraph_node.

Seems OK, however..
> Index: src/gcc/gimplify.c
> ===================================================================
> --- src.orig/gcc/gimplify.c	2011-03-19 01:16:24.000000000 +0100
> +++ src/gcc/gimplify.c	2011-03-19 01:54:42.000000000 +0100
> @@ -959,11 +959,11 @@ copy_if_shared (tree *tp)
>  static void
>  unshare_body (tree *body_p, tree fndecl)
>  {
> -  struct cgraph_node *cgn = cgraph_node (fndecl);
> +  struct cgraph_node *cgn = cgraph_get_node (fndecl);
>  
>    copy_if_shared (body_p);
>  
> -  if (body_p == &DECL_SAVED_TREE (fndecl))
> +  if (cgn && body_p == &DECL_SAVED_TREE (fndecl))

The non-NULL check is here because of gimplification happening before cgraph construction?
> Index: src/gcc/passes.c
> ===================================================================
> --- src.orig/gcc/passes.c	2011-03-19 01:16:23.000000000 +0100
> +++ src/gcc/passes.c	2011-03-19 01:54:42.000000000 +0100
> @@ -1344,7 +1344,7 @@ pass_init_dump_file (struct opt_pass *pa
>        if (dump_file && current_function_decl)
>  	{
>  	  const char *dname, *aname;
> -	  struct cgraph_node *node = cgraph_node (current_function_decl);
> +	  struct cgraph_node *node = cgraph_get_node (current_function_decl);

Don't you want cgraph_do_get_node on those places that will ICE anyway?
> Index: src/gcc/tree-ssa-alias.c
> ===================================================================
> --- src.orig/gcc/tree-ssa-alias.c	2011-03-19 01:16:23.000000000 +0100
> +++ src/gcc/tree-ssa-alias.c	2011-03-19 01:54:42.000000000 +0100
> @@ -1246,14 +1246,15 @@ ref_maybe_used_by_call_p_1 (gimple call,
>  
>    /* Check if base is a global static variable that is not read
>       by the function.  */
> -  if (TREE_CODE (base) == VAR_DECL
> +  if (callee != NULL_TREE
> +      && TREE_CODE (base) == VAR_DECL

Why non-NULL tests are needed here?  It seems that at the time cgraph is created we should have
nodes for all accessible functions.

What I wonder about is that we have similar API for annotations.  Here we have
var_ann_t for type name
var_ann (var) for what cgraph_get_node is
get_var_ann (var) for what cgraph_get_create_node is
create_var_ann (var) for hwat cgraph_create_node is.

So we may want to be consistent here. I never had problem with overlaping
struct and function obvoiusly, but if people disagree, what about:

cgraph_create_node = crate node and aborts if already exist
cgraph_get_node = return node or create noe
cgraph_maybe_get_node = return node or NULL
cgraph_do_get_node = return node and abort if NULL.

We may later even want to introduce our popular cgraph_node_d/cgraph_node_t and rename back cgraph_do_get_node to cgraph_node,
since it is is the most common accestor.
I would preffer to do that incrementally so we can merge ipa-inline changes.

Honza

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/4] Tweaks to C++ -> call graph interface
  2011-03-19 19:30 ` [PATCH 2/4] Tweaks to C++ " Martin Jambor
@ 2011-03-23 16:55   ` Jan Hubicka
  0 siblings, 0 replies; 13+ messages in thread
From: Jan Hubicka @ 2011-03-23 16:55 UTC (permalink / raw)
  To: Martin Jambor; +Cc: GCC Patches, Jan Hubicka

> I concede that my understanding of the C++ front-end inner workings
> are quite narrow and so the folling is basically a suggestion.  But it
> seems to me that at a few places where C++ queries the call graph for
> a node, the lazy node creation is not necessary.  If a maintainer can
> verify and approve (parts of) this after the big patch is committed,
> it would be a nice cleanup too.
> 
> Thanks,
> 
> Martin
> 
> 
> Index: src/gcc/cp/class.c
> ===================================================================
> --- src.orig/gcc/cp/class.c	2011-03-18 19:34:07.000000000 +0100
> +++ src/gcc/cp/class.c	2011-03-18 19:34:38.000000000 +0100
> @@ -8405,7 +8405,7 @@ cp_fold_obj_type_ref (tree ref, tree kno
>  				  DECL_VINDEX (fndecl)));
>  #endif
>  
> -  cgraph_get_create_node (fndecl)->local.vtable_method = true;
> +  cgraph_get_node (fndecl)->local.vtable_method = true;

I believe that vtable_method is ugly hack to work around the fact that we was
not able to optimize away functions that has address taken.  Perhaps this can
just be removed now?
>  
>    return build_address (fndecl);
>  }
> Index: src/gcc/cp/decl2.c
> ===================================================================
> --- src.orig/gcc/cp/decl2.c	2011-03-18 19:34:07.000000000 +0100
> +++ src/gcc/cp/decl2.c	2011-03-18 19:34:39.000000000 +0100
> @@ -3375,12 +3375,12 @@ cxx_callgraph_analyze_expr (tree *tp, in
>      case PTRMEM_CST:
>        if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
>  	cgraph_mark_address_taken_node (
> -			      cgraph_get_create_node (PTRMEM_CST_MEMBER (t)));
> +				  cgraph_do_get_node (PTRMEM_CST_MEMBER (t)));

I believe this si not safe in general, since it happens at cgraph construction time.
However perhaps all of those are gimplified away now?
>        break;
>      case BASELINK:
>        if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
>  	cgraph_mark_address_taken_node (
> -			      cgraph_get_create_node (BASELINK_FUNCTIONS (t)));
> +				  cgraph_do_get_node (BASELINK_FUNCTIONS (t)));
>        break;
>      case VAR_DECL:
>        if (DECL_CONTEXT (t)
> @@ -3893,7 +3893,7 @@ cp_write_global_declarations (void)
>  	  if (!DECL_EXTERNAL (decl)
>  	      && decl_needed_p (decl)
>  	      && !TREE_ASM_WRITTEN (decl)
> -	      && !cgraph_get_create_node (decl)->local.finalized)
> +	      && !cgraph_get_node (decl)->local.finalized)
>  	    {
>  	      /* We will output the function; no longer consider it in this
>  		 loop.  */
> Index: src/gcc/cp/method.c
> ===================================================================
> --- src.orig/gcc/cp/method.c	2011-03-18 19:34:07.000000000 +0100
> +++ src/gcc/cp/method.c	2011-03-18 19:34:40.000000000 +0100
> @@ -260,7 +260,7 @@ make_alias_for_thunk (tree function)
>    if (!flag_syntax_only)
>      {
>        struct cgraph_node *aliasn;
> -      aliasn = cgraph_same_body_alias (cgraph_get_create_node (function),
> +      aliasn = cgraph_same_body_alias (cgraph_do_get_node (function),
>  				       alias, function);
>        DECL_ASSEMBLER_NAME (function);
>        gcc_assert (aliasn != NULL);
> @@ -379,7 +379,7 @@ use_thunk (tree thunk_fndecl, bool emit_
>    a = nreverse (t);
>    DECL_ARGUMENTS (thunk_fndecl) = a;
>    TREE_ASM_WRITTEN (thunk_fndecl) = 1;
> -  cgraph_add_thunk (cgraph_get_create_node (function), thunk_fndecl, function,
> +  cgraph_add_thunk (cgraph_do_get_node (function), thunk_fndecl, function,

These two ought t be safe.
>  		    this_adjusting, fixed_offset, virtual_value,
>  		    virtual_offset, alias);
>  
> Index: src/gcc/cp/optimize.c
> ===================================================================
> --- src.orig/gcc/cp/optimize.c	2011-03-18 19:34:07.000000000 +0100
> +++ src/gcc/cp/optimize.c	2011-03-18 19:34:40.000000000 +0100
> @@ -309,8 +309,9 @@ maybe_clone_body (tree fn)
>  	  && (!DECL_ONE_ONLY (fns[0])
>  	      || (HAVE_COMDAT_GROUP
>  		  && DECL_WEAK (fns[0])))
> -	  && cgraph_same_body_alias (cgraph_get_create_node (fns[0]), clone,
> -				     fns[0]))
> +	  && (flag_syntax_only
> +	      || cgraph_same_body_alias (cgraph_do_get_node (fns[0]), clone,
> +					 fns[0])))

Same here, the node we are producing alias of should exist.
>  	{
>  	  alias = true;
>  	  if (DECL_ONE_ONLY (fns[0]))
> @@ -424,8 +425,8 @@ maybe_clone_body (tree fn)
>  	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
>  	     virtual, it goes into the same comdat group as well.  */
>  	  DECL_COMDAT_GROUP (fns[2]) = comdat_group;
> -	  base_dtor_node = cgraph_get_create_node (fns[0]);
> -	  deleting_dtor_node = cgraph_get_create_node (fns[2]);
> +	  base_dtor_node = cgraph_get_node (fns[0]);
> +	  deleting_dtor_node = cgraph_get_node (fns[2]);
>  	  gcc_assert (base_dtor_node->same_comdat_group == NULL);
>  	  gcc_assert (deleting_dtor_node->same_comdat_group == NULL);
do_get_node here? 
I am not at all sure why function we are cloning should have a node attached given
that it is an abstract function. Or do I miss something?

Honza
>  	  base_dtor_node->same_comdat_group = deleting_dtor_node;

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/4] Tweaks to objc -> call graph interface
  2011-03-19 19:30 ` [PATCH 4/4] Tweaks to objc -> call graph interface Martin Jambor
@ 2011-03-23 16:56   ` Jan Hubicka
  0 siblings, 0 replies; 13+ messages in thread
From: Jan Hubicka @ 2011-03-23 16:56 UTC (permalink / raw)
  To: Martin Jambor; +Cc: GCC Patches, Jan Hubicka

> Hi,
> 
> thi is really only based on successful testing and not much analyzis
> of the context but it seems that we don't need lazy node construction
> here.  It would be nice not to have it after the big patch gets in.
> 
> Thanks,
> 
> Martin
> 
> 
> 2011-03-18  Martin Jambor  <mjambor@suse.cz>
> 
> 	* objc-act.c (mark_referenced_methods): Call cgraph_do_get_node
> 	instead of cgraph_get_create_node.

Yes, this seems safe to me. Functions in protocols are finished and thus have
cgraph node.
Honza

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/4] A tweak to fortran -> call graph interface
  2011-03-19 19:30 ` [PATCH 3/4] A tweak to fortran -> call graph interface Martin Jambor
@ 2011-03-23 16:57   ` Jan Hubicka
  0 siblings, 0 replies; 13+ messages in thread
From: Jan Hubicka @ 2011-03-23 16:57 UTC (permalink / raw)
  To: Martin Jambor; +Cc: GCC Patches, Jan Hubicka

> Hi,
> 
> it seems to me that fortran can call cgraph_create_node directly
> without checking for its existence first.
> 
> Thanks,
> 
> Martin
> 
> 
> 2011-03-18  Martin Jambor  <mjambor@suse.cz>
> 
> 	* trans-decl.c (gfc_generate_function_code): Call cgraph_create_node
> 	instead of cgraph_get_create_node.
> 
> Index: src/gcc/fortran/trans-decl.c
> ===================================================================
> --- src.orig/gcc/fortran/trans-decl.c	2011-03-18 19:45:10.000000000 +0100
> +++ src/gcc/fortran/trans-decl.c	2011-03-18 19:45:12.000000000 +0100
> @@ -4924,7 +4924,7 @@ gfc_generate_function_code (gfc_namespac
>    if (decl_function_context (fndecl))
>      /* Register this function with cgraph just far enough to get it
>         added to our parent's nested function list.  */
> -    (void) cgraph_get_create_node (fndecl);
> +    (void) cgraph_create_node (fndecl);

this happens when function node is being build so indeed we want to create node here.
Honza

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/4] Remove cgraph_node function and fixup all callers
  2011-03-23  9:09   ` Jan Hubicka
@ 2011-03-25 10:25     ` Martin Jambor
  2011-03-25 17:02       ` Jan Hubicka
  0 siblings, 1 reply; 13+ messages in thread
From: Martin Jambor @ 2011-03-25 10:25 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: GCC Patches

Hi,

On Wed, Mar 23, 2011 at 10:08:53AM +0100, Jan Hubicka wrote:
> > 2011-03-18  Martin Jambor  <mjambor@suse.cz>
> > 
> > 	* cgraph.h (cgraph_node): Remove function declaration.
> > 	(cgraph_create_node): Declare.
> > 	(cgraph_get_create_node): Likewise.
> > 	(cgraph_do_get_node): New function.
> > 
> > 	* cgraph.c (cgraph_create_node): Renamed to cgraph_create_node_1.
> > 	Updated all callers.
> > 	(cgraph_node): Renamed to cgraph_create_node, assert that a node for
> > 	the decl does not already exist.  Call cgraph_get_create_node instead
> > 	of cgraph_node.
> > 	(cgraph_get_create_node): New function.
> > 	(cgraph_same_body_alias): Update comment.
> > 	(cgraph_set_call_stmt): Call cgraph_do_get_node instead of cgraph_node.
> > 	(cgraph_update_edges_for_call_stmt): Likewise.
> > 	(cgraph_clone_edge): Likewise.
> > 	(cgraph_create_virtual_clone): Likewise.
> > 	(cgraph_set_call_stmt): Call cgraph_get_create_node instead of
> > 	cgraph_node.
> > 	(cgraph_local_info): Call cgraph_get_node instead of cgraph_node,
> > 	handle NULL return value.
> > 	(cgraph_global_info): Likewise.
> > 	(cgraph_rtl_info): Likewise.
> > 	(cgraph_add_new_function): Call cgraph_create_node or
> > 	cgraph_get_create_node instead of cgraph_node.
> > 
> > 	* cgraphbuild.c (record_reference): Call cgraph_get_create_node
> > 	instead of cgraph_node.
> > 	(record_eh_tables): Likewise.
> > 	(mark_address): Likewise.
> > 	(mark_load): Likewise.
> > 	(build_cgraph_edges): Call cgraph_get_node and cgraph_get_create_node
> > 	instead of cgraph_node.
> > 	(rebuild_cgraph_edges): Likewise.
> > 	(cgraph_rebuild_references): Call cgraph_get_node instead of
> > 	cgraph_node.
> > 	(remove_cgraph_callee_edges): Likewise.
> > 
> > 	* cgraphunit.c (cgraph_finalize_function): Call cgraph_get_create_node
> > 	instead of cgraph_node.
> > 	(cgraph_mark_if_needed): Call cgraph_get_node instead of cgraph_node.
> > 	(verify_cgraph_node): Likewise.
> > 	(cgraph_analyze_functions): Likewise.
> > 	(cgraph_preserve_function_body_p): Likewise.
> > 	(save_inline_function_body): Likewise.
> > 	(save_inline_function_body): Likewise.
> > 	(cgraph_copy_node_for_versioning): Call cgraph_create_node instead of
> > 	cgraph_node.
> > 
> > 	* tree-inline.c (copy_bb): Call cgraph_get_node instead of cgraph_node.
> > 	(estimate_num_insns): Likewise and handle returned NULL.
> > 	(optimize_inline_calls): Call cgraph_get_node instead of cgraph_node.
> > 	(tree_function_versioning): Call cgraph_do_get_node instead of
> > 	cgraph_node.
> > 
> > 	* lto-symtab.c (lto_symtab_merge_cgraph_nodes_1): Call
> > 	cgraph_create_node instead of cgraph_node.
> > 
> > 	* c-decl.c (finish_function): Call cgraph_get_create_node instead
> > 	of cgraph_node.
> > 	* c-family/c-gimplify.c (c_genericize): Likewise.
> > 	* lto-cgraph.c (input_node): Likewise.
> > 	* lto-streamer-in.c (input_function): Likewise.
> > 
> > 	* except.c (set_nothrow_function_flags): Call cgraph_get_node instead
> > 	of cgraph_node.
> > 	* final.c (rest_of_clean_state): Likewise.
> > 	* gimple-iterator.c (update_call_edge_frequencies): Likewise.
> > 	* passes.c (pass_init_dump_file): Likewise.
> > 	(execute_all_ipa_transforms): Likewise.
> > 	(function_called_by_processed_nodes_p): Likewise.
> > 	* predict.c (maybe_hot_frequency_p): Likewise.
> > 	(probably_never_executed_bb_p): Likewise.
> > 	(compute_function_frequency): Likewise.
> > 	* tree-nested.c (check_for_nested_with_variably_modified): Likewise.
> > 	(unnest_nesting_tree_1): Likewise.
> > 	(lower_nested_functions): Likewise.
> > 	* tree-optimize.c (execute_fixup_cfg): Likewise.
> > 	(tree_rest_of_compilation): Likewise.
> > 	* tree-optimize.c (execute_fixup_cfg): Likewise.
> > 	(tree_rest_of_compilation): Likewise.
> > 	* tree-profile.c (gimple_gen_ic_func_profiler): Likewise.
> > 	* tree-sra.c (ipa_early_sra): Likewise.
> > 	* tree-ssa-loop-ivopts.c (computation_cost): Likewise.
> > 	* config/i386/i386.c (ix86_compute_frame_layout): Likewise.
> > 	* ipa.c (record_cdtor_fn): Likewise.
> > 	* ipa-inline.c (cgraph_early_inlining): Likewise.
> > 	(compute_inline_parameters_for_current): Likewise.
> > 	* ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
> > 	* ipa-pure-const.c (local_pure_const): Likewise.
> > 	* ipa-split.c (split_function): Likewise.
> > 	(split_function): Likewise.
> > 	(execute_split_functions): Likewise.
> > 
> > 	* lto-streamer-in.c (lto_read_body): Call cgraph_do_get_node instead
> > 	of cgraph_node.
> > 	* omp-low.c (new_omp_context): Likewise.
> > 	(create_task_copyfn): Likewise.
> > 	* tree-emutls.c (lower_emutls_function_body): Likewise.
> > 	* ipa-struct-reorg.c (update_cgraph_with_malloc_call): Likewise.
> > 	* ipa-type-escape.c (check_call): Likewise.
> > 	* matrix-reorg.c (transform_allocation_sites): Likewise.
> > 
> > 	* gimplify.c (unshare_body): Call cgraph_get_node instead of
> > 	cgraph_node, handle NULL return value.
> > 	(unvisit_body): Likewise.
> > 	(gimplify_body): Likewise.
> > 	* predict.c (optimize_function_for_size_p): Likewise.
> > 	* tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Likewise.
> > 	(call_may_clobber_ref_p_1): Likewise.
> > 
> > 	* varasm.c (function_section_1): Call cgraph_get_node instead of
> > 	cgraph_node and handle returned NULL.
> > 	(assemble_start_function): Likewise.
> > 	(mark_decl_referenced): Call cgraph_get_create_node instead of
> > 	cgraph_node.
> > 	(assemble_alias): Likewise.
> > 
> > gcc/c-family/
> > 	* c-gimplify.c (c_genericize): Call cgraph_get_create_node instead
> > 
> > gcc/cp/
> > 	* cp/class.c (cp_fold_obj_type_ref): Call cgraph_get_create_node
> > 	instead of cgraph_node.
> > 	* cp/decl2.c (cxx_callgraph_analyze_expr): Likewise.
> > 	(cp_write_global_declarations): Likewise.
> > 	* cp/optimize.c (maybe_clone_body): Likewise.
> > 	(maybe_clone_body): Likewise.
> > 	* cp/semantics.c (maybe_add_lambda_conv_op): Likewise.
> > 	* cp/mangle.c (mangle_decl): Likewise.
> > 	* cp/method.c (make_alias_for_thunk): Likewise.
> > 	(use_thunk): Likewise.
> > 
> > gcc/ada/
> > 	* gcc-interface/utils.c (end_subprog_body): Call
> > 	cgraph_get_create_node instead of cgraph_node.
> > 
> > gcc/fortran/
> > 	* trans-decl.c (gfc_generate_function_code): Call
> > 	cgraph_get_create_node instead of cgraph_node.
> > 
> > gcc/java/
> > 	* decl.c (java_mark_decl_local): Call cgraph_get_node instead of
> > 	cgraph_node and handle returned NULL.
> > 
> > gcc/objc/
> > 	* objc-act.c (mark_referenced_methods): Call cgraph_get_create_node
> > 	instead of cgraph_node.
> 
> Seems OK, however..

To what extent is this an approval? :-)

> > Index: src/gcc/gimplify.c
> > ===================================================================
> > --- src.orig/gcc/gimplify.c	2011-03-19 01:16:24.000000000 +0100
> > +++ src/gcc/gimplify.c	2011-03-19 01:54:42.000000000 +0100
> > @@ -959,11 +959,11 @@ copy_if_shared (tree *tp)
> >  static void
> >  unshare_body (tree *body_p, tree fndecl)
> >  {
> > -  struct cgraph_node *cgn = cgraph_node (fndecl);
> > +  struct cgraph_node *cgn = cgraph_get_node (fndecl);
> >  
> >    copy_if_shared (body_p);
> >  
> > -  if (body_p == &DECL_SAVED_TREE (fndecl))
> > +  if (cgn && body_p == &DECL_SAVED_TREE (fndecl))
> 
> The non-NULL check is here because of gimplification happening
> before cgraph construction?

One of my notes I took during development says: "unshare_body can
request a non-existing cgraph_node if called from
finalize_size_functions in stor-layout.c."  And a quick test yesterday
revealed that it can be also called when generating profile
(create_coverage->cgraph_build_static_cdtor_1->gimplify_function_tree).
So it's basically corner cases.

> > Index: src/gcc/passes.c
> > ===================================================================
> > --- src.orig/gcc/passes.c	2011-03-19 01:16:23.000000000 +0100
> > +++ src/gcc/passes.c	2011-03-19 01:54:42.000000000 +0100
> > @@ -1344,7 +1344,7 @@ pass_init_dump_file (struct opt_pass *pa
> >        if (dump_file && current_function_decl)
> >  	{
> >  	  const char *dname, *aname;
> > -	  struct cgraph_node *node = cgraph_node (current_function_decl);
> > +	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
> 
> Don't you want cgraph_do_get_node on those places that will ICE anyway?

No, the other way round.  I only used cgraph_do_get_node when it would
not ICE immediately but might later, like when the result was passed
to a caller or stored in some data structure for later use.  However
using it here is certainly possible, if you like.

> > Index: src/gcc/tree-ssa-alias.c
> > ===================================================================
> > --- src.orig/gcc/tree-ssa-alias.c	2011-03-19 01:16:23.000000000 +0100
> > +++ src/gcc/tree-ssa-alias.c	2011-03-19 01:54:42.000000000 +0100
> > @@ -1246,14 +1246,15 @@ ref_maybe_used_by_call_p_1 (gimple call,
> >  
> >    /* Check if base is a global static variable that is not read
> >       by the function.  */
> > -  if (TREE_CODE (base) == VAR_DECL
> > +  if (callee != NULL_TREE
> > +      && TREE_CODE (base) == VAR_DECL
> 
> Why non-NULL tests are needed here?  It seems that at the time
> cgraph is created we should have nodes for all accessible functions.

Almost.  We do not have a node for __builtin_GOMP_parallel_start when
we examine a call from dse_possible_dead_store_p.  It would be nice in
general if OMP made call graph nodes for its new functions in some
more defined manner.  At this point it relies on cgraphbuild.c and
apparently even that is sometimes not enough.  Should I add a FIXME
here?

The failing tests are gcc.dg/autopar/reduc-1.c and
gcc.dg/autopar/reduc-2.c.

> 
> What I wonder about is that we have similar API for annotations.  Here we have
> var_ann_t for type name
> var_ann (var) for what cgraph_get_node is
> get_var_ann (var) for what cgraph_get_create_node is
> create_var_ann (var) for hwat cgraph_create_node is.
> 
> So we may want to be consistent here. I never had problem with overlaping
> struct and function obvoiusly, but if people disagree, what about:
> 
> cgraph_create_node = crate node and aborts if already exist
> cgraph_get_node = return node or create noe
> cgraph_maybe_get_node = return node or NULL
> cgraph_do_get_node = return node and abort if NULL.
> 
> We may later even want to introduce our popular cgraph_node_d/cgraph_node_t and rename back cgraph_do_get_node to cgraph_node,
> since it is is the most common accestor.
> I would preffer to do that incrementally so we can merge ipa-inline changes.

Frankly, I think it is too much work for very little gain, and it
would cause a lot of trouble for anyone maintaining their patches or
branches.  Moreover, changing re-using function names of
cgraph_get_node and cgraph_node while changing their behavior seems
like a bad idea to me.

Nevertheless, there seems to be no opposition to the interface changes
I proposed so I am going to split the huge patch some more and seek
approval for the individual pieces.

Thanks,

Martin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/4] Remove cgraph_node function and fixup all callers
  2011-03-25 10:25     ` Martin Jambor
@ 2011-03-25 17:02       ` Jan Hubicka
  2011-03-28 10:08         ` Martin Jambor
  0 siblings, 1 reply; 13+ messages in thread
From: Jan Hubicka @ 2011-03-25 17:02 UTC (permalink / raw)
  To: Jan Hubicka, GCC Patches

> > Seems OK, however..
> 
> To what extent is this an approval? :-)

Approval only after you convince me on the questions bellow.

> 
> > > Index: src/gcc/gimplify.c
> > > ===================================================================
> > > --- src.orig/gcc/gimplify.c	2011-03-19 01:16:24.000000000 +0100
> > > +++ src/gcc/gimplify.c	2011-03-19 01:54:42.000000000 +0100
> > > @@ -959,11 +959,11 @@ copy_if_shared (tree *tp)
> > >  static void
> > >  unshare_body (tree *body_p, tree fndecl)
> > >  {
> > > -  struct cgraph_node *cgn = cgraph_node (fndecl);
> > > +  struct cgraph_node *cgn = cgraph_get_node (fndecl);
> > >  
> > >    copy_if_shared (body_p);
> > >  
> > > -  if (body_p == &DECL_SAVED_TREE (fndecl))
> > > +  if (cgn && body_p == &DECL_SAVED_TREE (fndecl))
> > 
> > The non-NULL check is here because of gimplification happening
> > before cgraph construction?
> 
> One of my notes I took during development says: "unshare_body can
> request a non-existing cgraph_node if called from
> finalize_size_functions in stor-layout.c."  And a quick test yesterday
> revealed that it can be also called when generating profile
> (create_coverage->cgraph_build_static_cdtor_1->gimplify_function_tree).
> So it's basically corner cases.

Hmm, so indeeed it is gimplificaiton before cgraph is updated. OK then.
> 
> > > Index: src/gcc/passes.c
> > > ===================================================================
> > > --- src.orig/gcc/passes.c	2011-03-19 01:16:23.000000000 +0100
> > > +++ src/gcc/passes.c	2011-03-19 01:54:42.000000000 +0100
> > > @@ -1344,7 +1344,7 @@ pass_init_dump_file (struct opt_pass *pa
> > >        if (dump_file && current_function_decl)
> > >  	{
> > >  	  const char *dname, *aname;
> > > -	  struct cgraph_node *node = cgraph_node (current_function_decl);
> > > +	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
> > 
> > Don't you want cgraph_do_get_node on those places that will ICE anyway?
> 
> No, the other way round.  I only used cgraph_do_get_node when it would
> not ICE immediately but might later, like when the result was passed
> to a caller or stored in some data structure for later use.  However
> using it here is certainly possible, if you like.

Hmm, OK.  The mutiplicity of cgraph accesstors is bit confusing.  For future
development I would preffer if people don't really need to worry about those
except for very corner cases (i.e. cgraph construction).

I would like to have one most common way to get cgraph node that is used
thorough backend.  I think it should be cgraph_do_get_node since in the backend
all functions that matters should be in cgraph.
> 
> > > Index: src/gcc/tree-ssa-alias.c
> > > ===================================================================
> > > --- src.orig/gcc/tree-ssa-alias.c	2011-03-19 01:16:23.000000000 +0100
> > > +++ src/gcc/tree-ssa-alias.c	2011-03-19 01:54:42.000000000 +0100
> > > @@ -1246,14 +1246,15 @@ ref_maybe_used_by_call_p_1 (gimple call,
> > >  
> > >    /* Check if base is a global static variable that is not read
> > >       by the function.  */
> > > -  if (TREE_CODE (base) == VAR_DECL
> > > +  if (callee != NULL_TREE
> > > +      && TREE_CODE (base) == VAR_DECL
> > 
> > Why non-NULL tests are needed here?  It seems that at the time
> > cgraph is created we should have nodes for all accessible functions.
> 
> Almost.  We do not have a node for __builtin_GOMP_parallel_start when
> we examine a call from dse_possible_dead_store_p.  It would be nice in
> general if OMP made call graph nodes for its new functions in some
> more defined manner.  At this point it relies on cgraphbuild.c and
> apparently even that is sometimes not enough.  Should I add a FIXME
> here?
> 
> The failing tests are gcc.dg/autopar/reduc-1.c and
> gcc.dg/autopar/reduc-2.c.


Yes, please add FIXME.  It is better to fix incrementally, but I gor previously troubles
with GOMP requiring or not requiring cgraph nodes to be present for interesting reasons
(i.e. I have to disable unreachable node removal before GOMP is ready).  We need to
clean this up.
> 
> > 
> > What I wonder about is that we have similar API for annotations.  Here we have
> > var_ann_t for type name
> > var_ann (var) for what cgraph_get_node is
> > get_var_ann (var) for what cgraph_get_create_node is
> > create_var_ann (var) for hwat cgraph_create_node is.
> > 
> > So we may want to be consistent here. I never had problem with overlaping
> > struct and function obvoiusly, but if people disagree, what about:
> > 
> > cgraph_create_node = crate node and aborts if already exist
> > cgraph_get_node = return node or create noe
> > cgraph_maybe_get_node = return node or NULL
> > cgraph_do_get_node = return node and abort if NULL.
> > 
> > We may later even want to introduce our popular cgraph_node_d/cgraph_node_t and rename back cgraph_do_get_node to cgraph_node,
> > since it is is the most common accestor.
> > I would preffer to do that incrementally so we can merge ipa-inline changes.
> 
> Frankly, I think it is too much work for very little gain, and it
> would cause a lot of trouble for anyone maintaining their patches or
> branches.  Moreover, changing re-using function names of
> cgraph_get_node and cgraph_node while changing their behavior seems
> like a bad idea to me.

Well, how many open patches people have? (except for me and Richi's inliner changes).

In general I do not like those small disprepancies in API names remaining in GCC forever,
so I would vote to change the names to be consistent at some point.  With you current
patch it is all matter of simple sed script, more or less, isn't it?

Honza
> 
> Nevertheless, there seems to be no opposition to the interface changes
> I proposed so I am going to split the huge patch some more and seek
> approval for the individual pieces.
> 
> Thanks,
> 
> Martin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/4] Remove cgraph_node function and fixup all callers
  2011-03-25 17:02       ` Jan Hubicka
@ 2011-03-28 10:08         ` Martin Jambor
  0 siblings, 0 replies; 13+ messages in thread
From: Martin Jambor @ 2011-03-28 10:08 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: GCC Patches

Hi,

On Fri, Mar 25, 2011 at 05:55:24PM +0100, Jan Hubicka wrote:
> > > > Index: src/gcc/passes.c
> > > > ===================================================================
> > > > --- src.orig/gcc/passes.c	2011-03-19 01:16:23.000000000 +0100
> > > > +++ src/gcc/passes.c	2011-03-19 01:54:42.000000000 +0100
> > > > @@ -1344,7 +1344,7 @@ pass_init_dump_file (struct opt_pass *pa
> > > >        if (dump_file && current_function_decl)
> > > >  	{
> > > >  	  const char *dname, *aname;
> > > > -	  struct cgraph_node *node = cgraph_node (current_function_decl);
> > > > +	  struct cgraph_node *node = cgraph_get_node (current_function_decl);
> > > 
> > > Don't you want cgraph_do_get_node on those places that will ICE anyway?
> > 
> > No, the other way round.  I only used cgraph_do_get_node when it would
> > not ICE immediately but might later, like when the result was passed
> > to a caller or stored in some data structure for later use.  However
> > using it here is certainly possible, if you like.
> 
> Hmm, OK.  The mutiplicity of cgraph accesstors is bit confusing.  For future
> development I would preffer if people don't really need to worry about those
> except for very corner cases (i.e. cgraph construction).
> 
> I would like to have one most common way to get cgraph node that is
> used thorough backend.  I think it should be cgraph_do_get_node
> since in the backend all functions that matters should be in cgraph.

My intention is really to make cgraph_get_node the one main accessor
function almost everyone should use to get their node.  Of course,
that means the return value should be checked somehow.  My gut feeling
at this moment is that now there are still too many cases where it can
return NULL legitimately (builtins, OMP builtins, mudflap stuff,
profile generation stuff, size functions, calls from front-end for
aliases...) that whoever wants to get their node will have to
differentiate in between the two cases when they can assert the result
is not NULL and when they cannot.

That will change only if we manage to create a node for each of these
problematic corner cases before someone can ask for it and not remove
it when removing unreachable nodes if folder can still put it into IL
(etc. etc.).

In fact, cgraph_do_get_node was originally a hack to help me identify
places where cgraph_get_node returns NULL.  And them I realized it
might be useful so I left it in the patch.  Actually, I anticipated a
request to remove it completely, not make it the default :-)

On the other hand I do agree that the other accessors (create,
get_create) should be used very rarely - preferably only in
cgraph(re)build and front-ends and we should continue efforts to weed
them out of everywhere else.

> > 
> > > > Index: src/gcc/tree-ssa-alias.c
> > > > ===================================================================
> > > > --- src.orig/gcc/tree-ssa-alias.c	2011-03-19 01:16:23.000000000 +0100
> > > > +++ src/gcc/tree-ssa-alias.c	2011-03-19 01:54:42.000000000 +0100
> > > > @@ -1246,14 +1246,15 @@ ref_maybe_used_by_call_p_1 (gimple call,
> > > >  
> > > >    /* Check if base is a global static variable that is not read
> > > >       by the function.  */
> > > > -  if (TREE_CODE (base) == VAR_DECL
> > > > +  if (callee != NULL_TREE
> > > > +      && TREE_CODE (base) == VAR_DECL
> > > 
> > > Why non-NULL tests are needed here?  It seems that at the time
> > > cgraph is created we should have nodes for all accessible functions.
> > 
> > Almost.  We do not have a node for __builtin_GOMP_parallel_start when
> > we examine a call from dse_possible_dead_store_p.  It would be nice in
> > general if OMP made call graph nodes for its new functions in some
> > more defined manner.  At this point it relies on cgraphbuild.c and
> > apparently even that is sometimes not enough.  Should I add a FIXME
> > here?
> > 
> > The failing tests are gcc.dg/autopar/reduc-1.c and
> > gcc.dg/autopar/reduc-2.c.
> 
> 
> Yes, please add FIXME.  It is better to fix incrementally, but I gor
> previously troubles with GOMP requiring or not requiring cgraph
> nodes to be present for interesting reasons (i.e. I have to disable
> unreachable node removal before GOMP is ready).  We need to clean
> this up.

OK

> > 
> > > 
> > > What I wonder about is that we have similar API for annotations.  Here we have
> > > var_ann_t for type name
> > > var_ann (var) for what cgraph_get_node is
> > > get_var_ann (var) for what cgraph_get_create_node is
> > > create_var_ann (var) for hwat cgraph_create_node is.
> > > 
> > > So we may want to be consistent here. I never had problem with overlaping
> > > struct and function obvoiusly, but if people disagree, what about:
> > > 
> > > cgraph_create_node = crate node and aborts if already exist
> > > cgraph_get_node = return node or create noe
> > > cgraph_maybe_get_node = return node or NULL
> > > cgraph_do_get_node = return node and abort if NULL.
> > > 
> > > We may later even want to introduce our popular
> > > cgraph_node_d/cgraph_node_t and rename back cgraph_do_get_node
> > > to cgraph_node, since it is is the most common accestor.  I
> > > would preffer to do that incrementally so we can merge
> > > ipa-inline changes.
> > 
> > Frankly, I think it is too much work for very little gain, and it
> > would cause a lot of trouble for anyone maintaining their patches or
> > branches.  Moreover, changing re-using function names of
> > cgraph_get_node and cgraph_node while changing their behavior seems
> > like a bad idea to me.
> 
> Well, how many open patches people have? (except for me and Richi's
> inliner changes).

I don't know but changing every "struct cgraph_node" in the source to
"cgraph_mode_t" (or _d?) seems quite invasive and time consuming and
boring... and did I say I don't think it is very useful?

> In general I do not like those small disprepancies in API names
> remaining in GCC forever, so I would vote to change the names to be
> consistent at some point.  With you current patch it is all matter
> of simple sed script, more or less, isn't it?

Well, not really.  My patch touches every call to "cgraph_node" there is
but it does not do the same for every currently existing call to
"cgraph_get_node" (which would also need to be examined and
potentially converted to the new _maybe_get_ variant).  Of course
changing every "struct cgraph_node" to "cgraph_node_favorite_letter"
would require even more modifications.

I also think that making cgraph_get_node to do something radically
different from what it does now (like lazily creating nodes) will lead
to confusion and bugs and it is not a good idea in general.

Having said that, I am willing to do the work necessary to make
cgraph_get_node to abort instead of returning NULL and introduce
cgraph_maybe_get_node which would not.  On the other hand, I would
very much prefer to spend my time on other issues than making cgraph
interface consistent with variable annotations interface.  If someone
else wants to do it, my patches will help them.

Is there any chance that you will be on IRC soon?  I'd just love to
get through this.

Thanks,

Martin

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2011-03-28 10:02 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-19 19:29 [PATCH 0/4] Remove (lots of) lazy call graph node construction Martin Jambor
2011-03-19 19:30 ` [PATCH 4/4] Tweaks to objc -> call graph interface Martin Jambor
2011-03-23 16:56   ` Jan Hubicka
2011-03-19 19:30 ` [PATCH 2/4] Tweaks to C++ " Martin Jambor
2011-03-23 16:55   ` Jan Hubicka
2011-03-19 19:30 ` [PATCH 1/4] Remove cgraph_node function and fixup all callers Martin Jambor
2011-03-23  9:09   ` Jan Hubicka
2011-03-25 10:25     ` Martin Jambor
2011-03-25 17:02       ` Jan Hubicka
2011-03-28 10:08         ` Martin Jambor
2011-03-19 19:30 ` [PATCH 3/4] A tweak to fortran -> call graph interface Martin Jambor
2011-03-23 16:57   ` Jan Hubicka
2011-03-23  8:53 ` [PATCH 0/4] Remove (lots of) lazy call graph node construction Jan Hubicka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).