diff mbox

Use conditional casting with symtab_node

Message ID CAGqM8fa78EHBy6BLUNZ-KOr6x8P6d8Ls3UowtGGq9_Bpmho8=g@mail.gmail.com
State New
Headers show

Commit Message

Lawrence Crowl Oct. 3, 2012, 12:32 a.m. UTC
Updated Patch

Add functions symtab_node_def::try_function and symtab_node_def::try_variable.
These function return a pointer to the more specific type (e.g. cgraph_node*)
if and only if the general type (symtab_node aka symtab_node_def*) is an
instance of the specific type.  These functions are essentially checked down
casts.

These functions reduce compile time and increase type safety when treating a
generic item as a more specific item.  In essence, the code change is from

  if (symtab_function_p (node))
    {
      struct cgraph_node *cnode = cgraph (node);
      ....
    }

to

  if (cgraph_node *cnode = node->try_function ())
    {
      ....
    }

The necessary conditional test defines a variable that holds a known good
pointer to the specific item and avoids subsequent conversion calls and
the assertion checks that may come with them.

When, the property test is embedded within a larger condition, the variable
declaration gets pulled out of the condition.  (This leaves some room for
using the variable inappropriately.)

  if (symtab_variable_p (node)
      && varpool (node)->finalized)
    varpool_analyze_node (varpool (node));

becomes

  varpool_node *vnode = node->try_variable ();
  if (vnode && vnode->finalized)
    varpool_analyze_node (vnode);

Note that we have converted two sets of assertions in the calls to varpool
into safe and efficient use of a variable.


There are remaining calls to symtab_function_p and symtab_variable_p that
do not involve a pointer to a more specific type.  These have been converted
to calls to a member functions symtab_node_def::is_function and
symtab_node_def::is_variable.  The original predicate functions have been
removed.


The cgraph.h header defined both a struct and a function with the name
varpool_node.  This name overloading can cause some unintuitive error messages
when, as is common in C++, one omits the struct keyword when using the type.
I have renamed the function to varpool_node_for_decl.


The new code bootstraps .616% faster with a 99% confidence of being faster.


Tested on x86_64.


Okay for trunk?


 }
@@ -1133,7 +1133,7 @@ lsei_start_function_in_partition (lto_sy

   if (lsei_end_p (lsei))
     return lsei;
-  if (!symtab_function_p (lsei_node (lsei))
+  if (!(lsei_node (lsei)->is_function ())
       || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
     lsei_next_function_in_partition (&lsei);

@@ -1146,7 +1146,7 @@ lsei_next_variable_in_partition (lto_sym
 {
   lsei_next (lsei);
   while (!lsei_end_p (*lsei)
-	 && (!symtab_variable_p (lsei_node (*lsei))
+	 && (!lsei_node (*lsei)->is_variable ()
 	     || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
(*lsei))))
     lsei_next (lsei);
 }
@@ -1159,7 +1159,7 @@ lsei_start_variable_in_partition (lto_sy

   if (lsei_end_p (lsei))
     return lsei;
-  if (!symtab_variable_p (lsei_node (lsei))
+  if (!lsei_node (lsei)->is_variable ()
       || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
     lsei_next_variable_in_partition (&lsei);

Comments

Martin Jambor Oct. 3, 2012, 12:06 p.m. UTC | #1
Hi,

On Tue, Oct 02, 2012 at 05:32:38PM -0700, Lawrence Crowl wrote:
> Updated Patch
> 
> Add functions symtab_node_def::try_function and symtab_node_def::try_variable.

Even though I hate to be bikeshedding, I must say I really dislike the
names, especially try_function.  Not only I believe it should be
consistent with the name of the type it returns but, more importantly,
it looks as if it had something to do with struct function which is an
entirely different thing.

I understand the names cgraph_node and varpool_node are slightly
anachronistic in the symtab world, but still I think that they are
perfectly usable, do not present a real obstacle to newcomers
(cgraph_nodes do form the call graph, after all) and we are all used
to them.  Therefore I'd be in favor of keeping them and changing the
try_stuff function names accordingly.

Thanks,

Martin

> These function return a pointer to the more specific type (e.g. cgraph_node*)
> if and only if the general type (symtab_node aka symtab_node_def*) is an
> instance of the specific type.  These functions are essentially checked down
> casts.
> 
> These functions reduce compile time and increase type safety when treating a
> generic item as a more specific item.  In essence, the code change is from
> 
>   if (symtab_function_p (node))
>     {
>       struct cgraph_node *cnode = cgraph (node);
>       ....
>     }
> 
> to
> 
>   if (cgraph_node *cnode = node->try_function ())
>     {
>       ....
>     }
> 
> The necessary conditional test defines a variable that holds a known good
> pointer to the specific item and avoids subsequent conversion calls and
> the assertion checks that may come with them.
> 
> When, the property test is embedded within a larger condition, the variable
> declaration gets pulled out of the condition.  (This leaves some room for
> using the variable inappropriately.)
> 
>   if (symtab_variable_p (node)
>       && varpool (node)->finalized)
>     varpool_analyze_node (varpool (node));
> 
> becomes
> 
>   varpool_node *vnode = node->try_variable ();
>   if (vnode && vnode->finalized)
>     varpool_analyze_node (vnode);
> 
> Note that we have converted two sets of assertions in the calls to varpool
> into safe and efficient use of a variable.
> 
> 
> There are remaining calls to symtab_function_p and symtab_variable_p that
> do not involve a pointer to a more specific type.  These have been converted
> to calls to a member functions symtab_node_def::is_function and
> symtab_node_def::is_variable.  The original predicate functions have been
> removed.
> 
> 
> The cgraph.h header defined both a struct and a function with the name
> varpool_node.  This name overloading can cause some unintuitive error messages
> when, as is common in C++, one omits the struct keyword when using the type.
> I have renamed the function to varpool_node_for_decl.
> 
> 
> The new code bootstraps .616% faster with a 99% confidence of being faster.
> 
> 
> Tested on x86_64.
> 
> 
> Okay for trunk?
> 
> 
> Index: gcc/ChangeLog
> 
> 2012-10-02  Lawrence Crowl  <crowl@google.com
> 
> 	* cgraph.h (varpool_node): Rename to varpool_node_for_decl.
> 	Adjust callers to match.
> 	(symtab_node_def::try_function): New.
> 	Change most calls to symtab_function_p with calls to
> 	symtab_node_def::try_function.
> 	(symtab_node_def::try_variable): New.
> 	Change most calls to symtab_variable_p with calls to
> 	symtab_node_def::try_variable.
> 	(symtab_function_p): Rename to symtab_node_def::is_function.
> 	Adjust remaining callers to match.
> 	(symtab_variable_p): Rename to symtab_node_def::is_variable.
> 	Adjust remaining callers to match.
> 	* cgraph.c (cgraph_node_for_asm): Remove redundant call to
> 	symtab_node_for_asm.
> 	* cgraphunit.c (symbol_finalized_and_needed): New.
> 	(symbol_finalized): New.
> 	(cgraph_analyze_functions): Split complicated conditionals out into
> 	above new functions.
> 
> 
> Index: gcc/lto-symtab.c
> ===================================================================
> --- gcc/lto-symtab.c	(revision 192010)
> +++ gcc/lto-symtab.c	(working copy)
> @@ -566,11 +566,11 @@ lto_symtab_merge_cgraph_nodes_1 (symtab_
> 
>        if (!symtab_real_symbol_p (e))
>  	continue;
> -      if (symtab_function_p (e)
> -	  && !DECL_BUILT_IN (e->symbol.decl))
> -	lto_cgraph_replace_node (cgraph (e), cgraph (prevailing));
> -      if (symtab_variable_p (e))
> -	lto_varpool_replace_node (varpool (e), varpool (prevailing));
> +      cgraph_node *ce = e->try_function ();
> +      if (ce && !DECL_BUILT_IN (e->symbol.decl))
> +	lto_cgraph_replace_node (ce, cgraph (prevailing));
> +      if (varpool_node *ve = e->try_variable ())
> +	lto_varpool_replace_node (ve, varpool (prevailing));
>      }
> 
>    return;
> Index: gcc/cgraphbuild.c
> ===================================================================
> --- gcc/cgraphbuild.c	(revision 192010)
> +++ gcc/cgraphbuild.c	(working copy)
> @@ -84,7 +84,7 @@ record_reference (tree *tp, int *walk_su
> 
>        if (TREE_CODE (decl) == VAR_DECL)
>  	{
> -	  struct varpool_node *vnode = varpool_node (decl);
> +	  struct varpool_node *vnode = varpool_node_for_decl (decl);
>  	  ipa_record_reference ((symtab_node)ctx->varpool_node,
>  				(symtab_node)vnode,
>  				IPA_REF_ADDR, NULL);
> @@ -123,7 +123,7 @@ record_type_list (struct cgraph_node *no
>  	  type = TREE_OPERAND (type, 0);
>  	  if (TREE_CODE (type) == VAR_DECL)
>  	    {
> -	      struct varpool_node *vnode = varpool_node (type);
> +	      struct varpool_node *vnode = varpool_node_for_decl (type);
>  	      ipa_record_reference ((symtab_node)node,
>  				    (symtab_node)vnode,
>  				    IPA_REF_ADDR, NULL);
> @@ -233,7 +233,7 @@ mark_address (gimple stmt, tree addr, vo
>    else if (addr && TREE_CODE (addr) == VAR_DECL
>  	   && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
>      {
> -      struct varpool_node *vnode = varpool_node (addr);
> +      struct varpool_node *vnode = varpool_node_for_decl (addr);
> 
>        ipa_record_reference ((symtab_node)data,
>  			    (symtab_node)vnode,
> @@ -262,7 +262,7 @@ mark_load (gimple stmt, tree t, void *da
>    else if (t && TREE_CODE (t) == VAR_DECL
>  	   && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
>      {
> -      struct varpool_node *vnode = varpool_node (t);
> +      struct varpool_node *vnode = varpool_node_for_decl (t);
> 
>        ipa_record_reference ((symtab_node)data,
>  			    (symtab_node)vnode,
> @@ -280,7 +280,7 @@ mark_store (gimple stmt, tree t, void *d
>    if (t && TREE_CODE (t) == VAR_DECL
>        && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
>      {
> -      struct varpool_node *vnode = varpool_node (t);
> +      struct varpool_node *vnode = varpool_node_for_decl (t);
> 
>        ipa_record_reference ((symtab_node)data,
>  			    (symtab_node)vnode,
> @@ -392,7 +392,7 @@ void
>  record_references_in_initializer (tree decl, bool only_vars)
>  {
>    struct pointer_set_t *visited_nodes = pointer_set_create ();
> -  struct varpool_node *node = varpool_node (decl);
> +  struct varpool_node *node = varpool_node_for_decl (decl);
>    struct record_reference_ctx ctx = {false, NULL};
> 
>    ctx.varpool_node = node;
> Index: gcc/cgraph.c
> ===================================================================
> --- gcc/cgraph.c	(revision 192010)
> +++ gcc/cgraph.c	(working copy)
> @@ -503,12 +503,15 @@ cgraph_add_thunk (struct cgraph_node *de
>  struct cgraph_node *
>  cgraph_node_for_asm (tree asmname)
>  {
> -  symtab_node node = symtab_node_for_asm (asmname);
> -
>    /* We do not want to look at inline clones.  */
> -  for (node = symtab_node_for_asm (asmname); node; node =
> node->symbol.next_sharing_asm_name)
> -    if (symtab_function_p (node) && !cgraph(node)->global.inlined_to)
> -      return cgraph (node);
> +  for (symtab_node node = symtab_node_for_asm (asmname);
> +       node;
> +       node = node->symbol.next_sharing_asm_name)
> +    {
> +      cgraph_node *cn = node->try_function ();
> +      if (cn && !cn->global.inlined_to)
> +	return cn;
> +    }
>    return NULL;
>  }
> 
> Index: gcc/cgraph.h
> ===================================================================
> --- gcc/cgraph.h	(revision 192010)
> +++ gcc/cgraph.h	(working copy)
> @@ -456,13 +456,56 @@ struct GTY(()) asm_node {
>  /* Symbol table entry.  */
>  union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"),
>  	   chain_prev ("%h.symbol.previous"))) symtab_node_def {
> +  /* Dynamic type testers. */
> +  bool GTY((skip)) is_function ();
> +  bool GTY((skip)) is_variable ();
> +  /* Conditional accessors return null if not the requested type.  */
> +  cgraph_node * GTY((skip)) try_function ();
> +  varpool_node * GTY((skip)) try_variable ();
> +
>    struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol;
> -  /* Use cgraph (symbol) accessor to get cgraph_node.  */
> +  /* To access the following fields,
> +     use the conditional accessors try_function and try_variable above
> +     or the asserting accessor functions cgraph and varpool.  */
>    struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function;
> -  /* Use varpool (symbol) accessor to get varpool_node.  */
>    struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable;
>  };
> 
> +/* Report whether or not THIS symtab node is a function, aka cgraph_node.  */
> +
> +inline bool
> +symtab_node_def::is_function ()
> +{
> +  return symbol.type == SYMTAB_FUNCTION;
> +}
> +
> +/* Report whether or not THIS symtab node is a vriable, aka varpool_node.  */
> +
> +inline bool
> +symtab_node_def::is_variable ()
> +{
> +  return symbol.type == SYMTAB_VARIABLE;
> +}
> +
> +/* If THIS symtab node is a function, return a pointer to the cgraph_node,
> +   otherwise return NULL.  */
> +
> +inline cgraph_node *
> +symtab_node_def::try_function ()
> +{
> +  return is_function () ? &x_function : NULL;
> +}
> +
> +/* If THIS symtab node is a variable, return a pointer to the varpool_node,
> +   otherwise return NULL.  */
> +
> +inline varpool_node *
> +symtab_node_def::try_variable()
> +{
> +  return is_variable () ? &x_variable : NULL;
> +}
> +
> +
>  extern GTY(()) symtab_node symtab_nodes;
>  extern GTY(()) int cgraph_n_nodes;
>  extern GTY(()) int cgraph_max_uid;
> @@ -685,7 +728,7 @@ bool cgraph_maybe_hot_edge_p (struct cgr
>  bool cgraph_optimize_for_size_p (struct cgraph_node *);
> 
>  /* In varpool.c  */
> -struct varpool_node *varpool_node (tree);
> +struct varpool_node *varpool_node_for_decl (tree);
>  struct varpool_node *varpool_node_for_asm (tree asmname);
>  void varpool_mark_needed_node (struct varpool_node *);
>  void debug_varpool (void);
> @@ -715,19 +758,6 @@ void varpool_add_new_variable (tree);
>  void symtab_initialize_asm_name_hash (void);
>  void symtab_prevail_in_asm_name_hash (symtab_node node);
> 
> -/* Return true when NODE is function.  */
> -static inline bool
> -symtab_function_p (symtab_node node)
> -{
> -  return node->symbol.type == SYMTAB_FUNCTION;
> -}
> -
> -/* Return true when NODE is variable.  */
> -static inline bool
> -symtab_variable_p (symtab_node node)
> -{
> -  return node->symbol.type == SYMTAB_VARIABLE;
> -}
> 
>  /* Return callgraph node for given symbol and check it is a function. */
>  static inline struct cgraph_node *
> @@ -800,10 +830,8 @@ varpool_first_variable (void)
>  {
>    symtab_node node;
>    for (node = symtab_nodes; node; node = node->symbol.next)
> -    {
> -      if (symtab_variable_p (node))
> -	return varpool (node);
> -    }
> +    if (varpool_node *vnode = node->try_variable ())
> +      return vnode;
>    return NULL;
>  }
> 
> @@ -813,10 +841,8 @@ varpool_next_variable (struct varpool_no
>  {
>    symtab_node node1 = (symtab_node) node->symbol.next;
>    for (; node1; node1 = node1->symbol.next)
> -    {
> -      if (symtab_variable_p (node1))
> -	return varpool (node1);
> -    }
> +    if (varpool_node *vnode1 = node1->try_variable ())
> +      return vnode1;
>    return NULL;
>  }
>  /* Walk all variables.  */
> @@ -832,9 +858,9 @@ varpool_first_static_initializer (void)
>    symtab_node node;
>    for (node = symtab_nodes; node; node = node->symbol.next)
>      {
> -      if (symtab_variable_p (node)
> -	  && DECL_INITIAL (node->symbol.decl))
> -	return varpool (node);
> +      varpool_node *vnode = node->try_variable ();
> +      if (vnode && DECL_INITIAL (node->symbol.decl))
> +	return vnode;
>      }
>    return NULL;
>  }
> @@ -846,9 +872,9 @@ varpool_next_static_initializer (struct
>    symtab_node node1 = (symtab_node) node->symbol.next;
>    for (; node1; node1 = node1->symbol.next)
>      {
> -      if (symtab_variable_p (node1)
> -	  && DECL_INITIAL (node1->symbol.decl))
> -	return varpool (node1);
> +      varpool_node *vnode1 = node1->try_variable ();
> +      if (vnode1 && DECL_INITIAL (node1->symbol.decl))
> +	return vnode1;
>      }
>    return NULL;
>  }
> @@ -865,8 +891,9 @@ varpool_first_defined_variable (void)
>    symtab_node node;
>    for (node = symtab_nodes; node; node = node->symbol.next)
>      {
> -      if (symtab_variable_p (node) && varpool (node)->analyzed)
> -	return varpool (node);
> +      varpool_node *vnode = node->try_variable ();
> +      if (vnode && vnode->analyzed)
> +	return vnode;
>      }
>    return NULL;
>  }
> @@ -878,8 +905,9 @@ varpool_next_defined_variable (struct va
>    symtab_node node1 = (symtab_node) node->symbol.next;
>    for (; node1; node1 = node1->symbol.next)
>      {
> -      if (symtab_variable_p (node1) && varpool (node1)->analyzed)
> -	return varpool (node1);
> +      varpool_node *vnode1 = node1->try_variable ();
> +      if (vnode1 && vnode1->analyzed)
> +	return vnode1;
>      }
>    return NULL;
>  }
> @@ -895,8 +923,9 @@ cgraph_first_defined_function (void)
>    symtab_node node;
>    for (node = symtab_nodes; node; node = node->symbol.next)
>      {
> -      if (symtab_function_p (node) && cgraph (node)->analyzed)
> -	return cgraph (node);
> +      cgraph_node *cn = node->try_function ();
> +      if (cn && cn->analyzed)
> +	return cn;
>      }
>    return NULL;
>  }
> @@ -908,8 +937,9 @@ cgraph_next_defined_function (struct cgr
>    symtab_node node1 = (symtab_node) node->symbol.next;
>    for (; node1; node1 = node1->symbol.next)
>      {
> -      if (symtab_function_p (node1) && cgraph (node1)->analyzed)
> -	return cgraph (node1);
> +      cgraph_node *cn1 = node1->try_function ();
> +      if (cn1 && cn1->analyzed)
> +	return cn1;
>      }
>    return NULL;
>  }
> @@ -925,10 +955,8 @@ cgraph_first_function (void)
>  {
>    symtab_node node;
>    for (node = symtab_nodes; node; node = node->symbol.next)
> -    {
> -      if (symtab_function_p (node))
> -	return cgraph (node);
> -    }
> +    if (cgraph_node *cn = node->try_function ())
> +      return cn;
>    return NULL;
>  }
> 
> @@ -938,10 +966,8 @@ cgraph_next_function (struct cgraph_node
>  {
>    symtab_node node1 = (symtab_node) node->symbol.next;
>    for (; node1; node1 = node1->symbol.next)
> -    {
> -      if (symtab_function_p (node1))
> -	return cgraph (node1);
> -    }
> +    if (cgraph_node *cn1 = node1->try_function ())
> +      return cn1;
>    return NULL;
>  }
>  /* Walk all functions.  */
> @@ -968,9 +994,9 @@ cgraph_first_function_with_gimple_body (
>    symtab_node node;
>    for (node = symtab_nodes; node; node = node->symbol.next)
>      {
> -      if (symtab_function_p (node)
> -	  && cgraph_function_with_gimple_body_p (cgraph (node)))
> -	return cgraph (node);
> +      cgraph_node *cn = node->try_function ();
> +      if (cn && cgraph_function_with_gimple_body_p (cn))
> +	return cn;
>      }
>    return NULL;
>  }
> @@ -982,9 +1008,9 @@ cgraph_next_function_with_gimple_body (s
>    symtab_node node1 = node->symbol.next;
>    for (; node1; node1 = node1->symbol.next)
>      {
> -      if (symtab_function_p (node1)
> -	  && cgraph_function_with_gimple_body_p (cgraph (node1)))
> -	return cgraph (node1);
> +      cgraph_node *cn1 = node1->try_function ();
> +      if (cn1 && cgraph_function_with_gimple_body_p (cn1))
> +	return cn1;
>      }
>    return NULL;
>  }
> @@ -1183,7 +1209,7 @@ cgraph_alias_aliased_node (struct cgraph
> 
>    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
>    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
> -  if (symtab_function_p (ref->referred))
> +  if (ref->referred->is_function ())
>      return ipa_ref_node (ref);
>    return NULL;
>  }
> @@ -1197,7 +1223,7 @@ varpool_alias_aliased_node (struct varpo
> 
>    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
>    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
> -  if (symtab_variable_p (ref->referred))
> +  if (ref->referred->is_variable ())
>      return ipa_ref_varpool_node (ref);
>    return NULL;
>  }
> @@ -1328,7 +1354,7 @@ symtab_real_symbol_p (symtab_node node)
>    struct cgraph_node *cnode;
>    struct ipa_ref *ref;
> 
> -  if (!symtab_function_p (node))
> +  if (!node->is_function ())
>      return true;
>    cnode = cgraph (node);
>    if (cnode->global.inlined_to)
> Index: gcc/tree-emutls.c
> ===================================================================
> --- gcc/tree-emutls.c	(revision 192010)
> +++ gcc/tree-emutls.c	(working copy)
> @@ -260,7 +260,7 @@ get_emutls_init_templ_addr (tree decl)
>    /* Create varpool node for the new variable and finalize it if it is
>       not external one.  */
>    if (DECL_EXTERNAL (to))
> -    varpool_node (to);
> +    varpool_node_for_decl (to);
>    else
>      varpool_add_new_variable (to);
>    return build_fold_addr_expr (to);
> @@ -332,7 +332,7 @@ new_emutls_decl (tree decl, tree alias_o
>    /* Create varpool node for the new variable and finalize it if it is
>       not external one.  */
>    if (DECL_EXTERNAL (to))
> -    varpool_node (to);
> +    varpool_node_for_decl (to);
>    else if (!alias_of)
>      varpool_add_new_variable (to);
>    else
> Index: gcc/ipa-reference.c
> ===================================================================
> --- gcc/ipa-reference.c	(revision 192010)
> +++ gcc/ipa-reference.c	(working copy)
> @@ -482,7 +482,7 @@ analyze_function (struct cgraph_node *fn
>    local = init_function_info (fn);
>    for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list,
> i, ref); i++)
>      {
> -      if (!symtab_variable_p (ref->referred))
> +      if (!ref->referred->is_variable ())
>  	continue;
>        var = ipa_ref_varpool_node (ref)->symbol.decl;
>        if (!is_proper_for_analysis (var))
> @@ -979,8 +979,6 @@ stream_out_bitmap (struct lto_simple_out
>  static void
>  ipa_reference_write_optimization_summary (void)
>  {
> -  struct cgraph_node *node;
> -  symtab_node snode;
>    struct lto_simple_output_block *ob
>      = lto_create_simple_output_block (LTO_section_ipa_reference);
>    unsigned int count = 0;
> @@ -994,12 +992,10 @@ ipa_reference_write_optimization_summary
>    /* See what variables we are interested in.  */
>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>      {
> -      struct varpool_node *vnode;
> -      snode = lto_symtab_encoder_deref (encoder, i);
> -      if (!symtab_variable_p (snode))
> -	continue;
> -      vnode = varpool (snode);
> -      if (bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      varpool_node *vnode = snode->try_variable ();
> +      if (vnode
> +	  && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
>  	  && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder))
>  	{
>  	  tree decl = vnode->symbol.decl;
> @@ -1013,10 +1009,12 @@ ipa_reference_write_optimization_summary
> 
>    if (ltrans_statics_bitcount)
>      for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
> -      if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder, i))
> -	  && write_node_summary_p (cgraph (snode),
> -				   encoder, ltrans_statics))
> +      {
> +	symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +	cgraph_node *cnode = snode->try_function ();
> +	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
>  	  count++;
> +      }
> 
>    streamer_write_uhwi_stream (ob->main_stream, count);
>    if (count)
> @@ -1027,17 +1025,15 @@ ipa_reference_write_optimization_summary
>    if (ltrans_statics_bitcount)
>      for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>        {
> -	snode = lto_symtab_encoder_deref (encoder, i);
> -	if (!symtab_function_p (snode))
> -	  continue;
> -	node = cgraph (snode);
> -	if (write_node_summary_p (node, encoder, ltrans_statics))
> +	symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +	cgraph_node *cnode = snode->try_function ();
> +	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
>  	  {
>  	    ipa_reference_optimization_summary_t info;
>  	    int node_ref;
> 
> -	    info = get_reference_optimization_summary (node);
> -	    node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
> +	    info = get_reference_optimization_summary (cnode);
> +	    node_ref = lto_symtab_encoder_encode (encoder, snode);
>  	    streamer_write_uhwi_stream (ob->main_stream, node_ref);
> 
>  	    stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
> Index: gcc/cgraphunit.c
> ===================================================================
> --- gcc/cgraphunit.c	(revision 192010)
> +++ gcc/cgraphunit.c	(working copy)
> @@ -386,7 +386,8 @@ referred_to_p (symtab_node node)
>    if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
>      return true;
>    /* For functions check also calls.  */
> -  if (symtab_function_p (node) && cgraph (node)->callers)
> +  cgraph_node *cn = node->try_function ();
> +  if (cn && cn->callers)
>      return true;
>    return false;
>  }
> @@ -809,7 +810,7 @@ process_function_and_variable_attributes
>  void
>  varpool_finalize_decl (tree decl)
>  {
> -  struct varpool_node *node = varpool_node (decl);
> +  struct varpool_node *node = varpool_node_for_decl (decl);
> 
>    gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
> 
> @@ -836,6 +837,35 @@ varpool_finalize_decl (tree decl)
>      varpool_assemble_decl (node);
>  }
> 
> +
> +/* Determine if a symbol is finalized and needed.  */
> +
> +inline static bool
> +symbol_finalized_and_needed (symtab_node node)
> +{
> +  if (cgraph_node *cnode = node->try_function ())
> +    return cnode->local.finalized
> +	   && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl);
> +  if (varpool_node *vnode = node->try_variable ())
> +    return vnode->finalized
> +	   && !DECL_EXTERNAL (vnode->symbol.decl)
> +	   && decide_is_variable_needed (vnode, vnode->symbol.decl);
> +  return false;
> +}
> +
> +/* Determine if a symbol is finalized.  */
> +
> +inline static bool
> +symbol_finalized (symtab_node node)
> +{
> +  if (cgraph_node *cnode= node->try_function ())
> +    return cnode->local.finalized;
> +  if (varpool_node *vnode = node->try_variable ())
> +    return vnode->finalized;
> +  return false;
> +}
> +
> +
>  /* Discover all functions and variables that are trivially needed, analyze
>     them as well as all functions and variables referred by them  */
> 
> @@ -870,13 +900,7 @@ cgraph_analyze_functions (void)
>  	   node != (symtab_node)first_analyzed
>  	   && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
>  	{
> -	  if ((symtab_function_p (node)
> -	       && cgraph (node)->local.finalized
> -	       && cgraph_decide_is_function_needed (cgraph (node), node->symbol.decl))
> -	      || (symtab_variable_p (node)
> -		  && varpool (node)->finalized
> -		  && !DECL_EXTERNAL (node->symbol.decl)
> -		  && decide_is_variable_needed (varpool (node), node->symbol.decl)))
> +	  if (symbol_finalized_and_needed (node))
>  	    {
>  	      enqueue_node (node);
>  	      if (!changed && cgraph_dump_file)
> @@ -903,18 +927,15 @@ cgraph_analyze_functions (void)
>  	  changed = true;
>  	  node = first;
>  	  first = (symtab_node)first->symbol.aux;
> -	  if (symtab_function_p (node) && cgraph (node)->local.finalized)
> +	  cgraph_node *cnode = node->try_function ();
> +	  if (cnode && cnode->local.finalized)
>  	    {
>  	      struct cgraph_edge *edge;
> -	      struct cgraph_node *cnode;
> -	      tree decl;
> -
> -	      cnode = cgraph (node);
> -	      decl = cnode->symbol.decl;
> +	      tree decl = cnode->symbol.decl;
> 
> -	      /* ??? It is possible to create extern inline function and later using
> -		 weak alias attribute to kill its body. See
> -		 gcc.c-torture/compile/20011119-1.c  */
> +	      /* ??? It is possible to create extern inline function
> +	      and later using weak alias attribute to kill its body.
> +	      See gcc.c-torture/compile/20011119-1.c  */
>  	      if (!DECL_STRUCT_FUNCTION (decl)
>  		  && (!cnode->alias || !cnode->thunk.alias)
>  		  && !cnode->thunk.thunk_p)
> @@ -929,23 +950,25 @@ cgraph_analyze_functions (void)
> 
>  	      for (edge = cnode->callees; edge; edge = edge->next_callee)
>  		if (edge->callee->local.finalized)
> -		  enqueue_node ((symtab_node)edge->callee);
> +		   enqueue_node ((symtab_node)edge->callee);
> 
> -	      /* 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.  */
> +	      /* 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.  */
>  	      if (DECL_ABSTRACT_ORIGIN (decl))
>  		{
> -		  struct cgraph_node *origin_node;
> -		  origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
> +		  struct cgraph_node *origin_node
> +	    	  = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
>  		  origin_node->abstract_and_needed = true;
>  		}
> -
>  	    }
> -	  else if (symtab_variable_p (node)
> -		   && varpool (node)->finalized)
> -	    varpool_analyze_node (varpool (node));
> +	  else
> +	    {
> +	      varpool_node *vnode = node->try_variable ();
> +	      if (vnode && vnode->finalized)
> +		varpool_analyze_node (vnode);
> +	    }
> 
>  	  if (node->symbol.same_comdat_group)
>  	    {
> @@ -956,8 +979,7 @@ cgraph_analyze_functions (void)
>  		enqueue_node (next);
>  	    }
>  	  for (i = 0; ipa_ref_list_reference_iterate
> (&node->symbol.ref_list, i, ref); i++)
> -	    if ((symtab_function_p (ref->referred) && cgraph
> (ref->referred)->local.finalized)
> -		|| (symtab_variable_p (ref->referred) && varpool (ref->referred)->finalized))
> +	    if (symbol_finalized (ref->referred))
>  	      enqueue_node (ref->referred);
>            cgraph_process_new_functions ();
>  	}
> @@ -985,10 +1007,9 @@ cgraph_analyze_functions (void)
>  	  symtab_remove_node (node);
>  	  continue;
>  	}
> -      if (symtab_function_p (node))
> +      if (cgraph_node *cnode = node->try_function ())
>  	{
>  	  tree decl = node->symbol.decl;
> -	  struct cgraph_node *cnode = cgraph (node);
> 
>  	  if (cnode->local.finalized && !gimple_has_body_p (decl)
>  	      && (!cnode->alias || !cnode->thunk.alias)
> @@ -1070,7 +1091,7 @@ handle_alias_pairs (void)
>  	}
> 
>        if (TREE_CODE (p->decl) == FUNCTION_DECL
> -          && target_node && symtab_function_p (target_node))
> +          && target_node && target_node->is_function ())
>  	{
>  	  struct cgraph_node *src_node = cgraph_get_node (p->decl);
>  	  if (src_node && src_node->local.finalized)
> @@ -1079,7 +1100,7 @@ handle_alias_pairs (void)
>  	  VEC_unordered_remove (alias_pair, alias_pairs, i);
>  	}
>        else if (TREE_CODE (p->decl) == VAR_DECL
> -	       && target_node && symtab_variable_p (target_node))
> +	       && target_node && target_node->is_variable ())
>  	{
>  	  varpool_create_variable_alias (p->decl, target_node->symbol.decl);
>  	  VEC_unordered_remove (alias_pair, alias_pairs, i);
> Index: gcc/cp/decl2.c
> ===================================================================
> --- gcc/cp/decl2.c	(revision 192010)
> +++ gcc/cp/decl2.c	(working copy)
> @@ -1778,7 +1778,7 @@ import_export_class (tree ctype)
>  static bool
>  var_finalized_p (tree var)
>  {
> -  return varpool_node (var)->finalized;
> +  return varpool_node_for_decl (var)->finalized;
>  }
> 
>  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
> @@ -1896,7 +1896,7 @@ maybe_emit_vtables (tree ctype)
>  	TREE_ASM_WRITTEN (vtbl) = 1;
>        else if (DECL_ONE_ONLY (vtbl))
>  	{
> -	  current = varpool_node (vtbl);
> +	  current = varpool_node_for_decl (vtbl);
>  	  if (last)
>  	    symtab_add_to_same_comdat_group ((symtab_node) current,
> (symtab_node) last);
>  	  last = current;
> Index: gcc/ipa-ref.c
> ===================================================================
> --- gcc/ipa-ref.c	(revision 192010)
> +++ gcc/ipa-ref.c	(working copy)
> @@ -42,7 +42,7 @@ ipa_record_reference (symtab_node referr
>    struct ipa_ref_list *list, *list2;
>    VEC(ipa_ref_t,gc) *old_references;
> 
> -  gcc_checking_assert (!stmt || symtab_function_p (referring_node));
> +  gcc_checking_assert (!stmt || referring_node->is_function ());
>    gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
> 
>    list = &referring_node->symbol.ref_list;
> Index: gcc/lto-cgraph.c
> ===================================================================
> --- gcc/lto-cgraph.c	(revision 192010)
> +++ gcc/lto-cgraph.c	(working copy)
> @@ -665,7 +665,7 @@ add_references (lto_symtab_encoder_t enc
>    int i;
>    struct ipa_ref *ref;
>    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
> -    if (symtab_function_p (ref->referred))
> +    if (ref->referred->is_function ())
>        add_node_to (encoder, ipa_ref_node (ref), false);
>      else
>        lto_symtab_encoder_encode (encoder, ref->referred);
> @@ -716,9 +716,8 @@ compute_ltrans_boundary (lto_symtab_enco
>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>      {
>        symtab_node node = lto_symtab_encoder_deref (encoder, i);
> -      if (symtab_variable_p (node))
> +      if (varpool_node *vnode = node->try_variable ())
>  	{
> -	  struct varpool_node *vnode = varpool (node);
>  	  if (DECL_INITIAL (vnode->symbol.decl)
>  	      && !lto_symtab_encoder_encode_initializer_p (encoder,
>  							   vnode)
> @@ -782,8 +781,8 @@ output_symtab (void)
>    for (i = 0; i < n_nodes; i++)
>      {
>        symtab_node node = lto_symtab_encoder_deref (encoder, i);
> -      if (symtab_function_p (node))
> -        lto_output_node (ob, cgraph (node), encoder);
> +      if (cgraph_node *cnode = node->try_function ())
> +        lto_output_node (ob, cnode, encoder);
>        else
>          lto_output_varpool_node (ob, varpool (node), encoder);
>  	
> @@ -969,7 +968,7 @@ input_varpool_node (struct lto_file_decl
>    order = streamer_read_hwi (ib) + order_base;
>    decl_index = streamer_read_uhwi (ib);
>    var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
> -  node = varpool_node (var_decl);
> +  node = varpool_node_for_decl (var_decl);
>    node->symbol.order = order;
>    if (order >= symtab_order)
>      symtab_order = order + 1;
> @@ -1130,14 +1129,14 @@ input_cgraph_1 (struct lto_file_decl_dat
>    /* AUX pointers should be all non-zero for function nodes read from
> the stream.  */
>  #ifdef ENABLE_CHECKING
>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
> -    gcc_assert (node->symbol.aux || !symtab_function_p (node));
> +    gcc_assert (node->symbol.aux || !node->is_function ());
>  #endif
>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>      {
>        int ref;
> -      if (symtab_function_p (node))
> +      if (cgraph_node *cnode = node->try_function ())
>  	{
> -	  ref = (int) (intptr_t) cgraph (node)->global.inlined_to;
> +	  ref = (int) (intptr_t) cnode->global.inlined_to;
> 
>  	  /* We share declaration of builtins, so we may read same node twice.  */
>  	  if (!node->symbol.aux)
> @@ -1146,9 +1145,9 @@ input_cgraph_1 (struct lto_file_decl_dat
> 
>  	  /* Fixup inlined_to from reference to pointer.  */
>  	  if (ref != LCC_NOT_FOUND)
> -	    cgraph (node)->global.inlined_to = cgraph (VEC_index
> (symtab_node, nodes, ref));
> +	    cnode->global.inlined_to = cgraph (VEC_index (symtab_node, nodes, ref));
>  	  else
> -	    cgraph (node)->global.inlined_to = NULL;
> +	    cnode->global.inlined_to = NULL;
>  	}
> 
>        ref = (int) (intptr_t) node->symbol.same_comdat_group;
> @@ -1160,7 +1159,7 @@ input_cgraph_1 (struct lto_file_decl_dat
>  	node->symbol.same_comdat_group = NULL;
>      }
>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
> -    node->symbol.aux = symtab_function_p (node) ? (void *)1 : NULL;
> +    node->symbol.aux = node->is_function () ? (void *)1 : NULL;
>    return nodes;
>  }
> 
> @@ -1435,7 +1434,6 @@ output_node_opt_summary (struct output_b
>  static void
>  output_cgraph_opt_summary (void)
>  {
> -  symtab_node node;
>    int i, n_nodes;
>    lto_symtab_encoder_t encoder;
>    struct output_block *ob = create_output_block (LTO_section_cgraph_opt_sum);
> @@ -1445,18 +1443,21 @@ output_cgraph_opt_summary (void)
>    encoder = ob->decl_state->symtab_node_encoder;
>    n_nodes = lto_symtab_encoder_size (encoder);
>    for (i = 0; i < n_nodes; i++)
> -    if (symtab_function_p (node = lto_symtab_encoder_deref (encoder, i))
> -	&& output_cgraph_opt_summary_p (cgraph (node)))
> -      count++;
> +    {
> +      symtab_node node = lto_symtab_encoder_deref (encoder, i);
> +      cgraph_node *cnode = node->try_function ();
> +      if (cnode && output_cgraph_opt_summary_p (cnode))
> +	count++;
> +    }
>    streamer_write_uhwi (ob, count);
>    for (i = 0; i < n_nodes; i++)
>      {
> -      node = lto_symtab_encoder_deref (encoder, i);
> -      if (symtab_function_p (node)
> -	  && output_cgraph_opt_summary_p (cgraph (node)))
> +      symtab_node node = lto_symtab_encoder_deref (encoder, i);
> +      cgraph_node *cnode = node->try_function ();
> +      if (cnode && output_cgraph_opt_summary_p (cnode))
>  	{
>  	  streamer_write_uhwi (ob, i);
> -	  output_node_opt_summary (ob, cgraph (node), encoder);
> +	  output_node_opt_summary (ob, cnode, encoder);
>  	}
>      }
>    produce_asm (ob, NULL);
> Index: gcc/lto-streamer-out.c
> ===================================================================
> --- gcc/lto-streamer-out.c	(revision 192010)
> +++ gcc/lto-streamer-out.c	(working copy)
> @@ -972,7 +972,6 @@ copy_function (struct cgraph_node *node)
>  static void
>  lto_output (void)
>  {
> -  struct cgraph_node *node;
>    struct lto_out_decl_state *decl_state;
>  #ifdef ENABLE_CHECKING
>    bitmap output = lto_bitmap_alloc ();
> @@ -988,10 +987,9 @@ lto_output (void)
>    for (i = 0; i < n_nodes; i++)
>      {
>        symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> -      if (!symtab_function_p (snode))
> -	continue;
> -      node = cgraph (snode);
> -      if (lto_symtab_encoder_encode_body_p (encoder, node)
> +      cgraph_node *node = snode->try_function ();
> +      if (node
> +	  && lto_symtab_encoder_encode_body_p (encoder, node)
>  	  && !node->alias
>  	  && !node->thunk.thunk_p)
>  	{
> @@ -1285,8 +1283,6 @@ produce_symtab (struct output_block *ob)
>    struct streamer_tree_cache_d *cache = ob->writer_cache;
>    char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
>    struct pointer_set_t *seen;
> -  struct cgraph_node *node;
> -  struct varpool_node *vnode;
>    struct lto_output_stream stream;
>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>    int i;
> @@ -1302,49 +1298,52 @@ produce_symtab (struct output_block *ob)
>       This is done so only to handle duplicated symbols in cgraph.  */
>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>      {
> -      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      cgraph_node *cnode = snode->try_function ();
> +      if (!cnode)
>  	continue;
> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
> -      if (DECL_EXTERNAL (node->symbol.decl))
> +      if (DECL_EXTERNAL (cnode->symbol.decl))
>  	continue;
> -      if (DECL_COMDAT (node->symbol.decl)
> -	  && cgraph_comdat_can_be_unshared_p (node))
> +      if (DECL_COMDAT (cnode->symbol.decl)
> +	  && cgraph_comdat_can_be_unshared_p (cnode))
>  	continue;
> -      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
> +      if ((cnode->alias && !cnode->thunk.alias) || cnode->global.inlined_to)
>  	continue;
> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
> +      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
>      }
>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>      {
> -      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      cgraph_node *cnode = snode->try_function ();
> +      if (!cnode)
>  	continue;
> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
> -      if (!DECL_EXTERNAL (node->symbol.decl))
> +      if (!DECL_EXTERNAL (cnode->symbol.decl))
>  	continue;
>        /* We keep around unused extern inlines in order to be able to inline
>  	 them indirectly or via vtables.  Do not output them to symbol
>  	 table: they end up being undefined and just consume space.  */
> -      if (!node->symbol.address_taken && !node->callers)
> +      if (!cnode->symbol.address_taken && !cnode->callers)
>  	continue;
> -      if (DECL_COMDAT (node->symbol.decl)
> -	  && cgraph_comdat_can_be_unshared_p (node))
> +      if (DECL_COMDAT (cnode->symbol.decl)
> +	  && cgraph_comdat_can_be_unshared_p (cnode))
>  	continue;
> -      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
> +      if ((cnode->alias && !cnode->thunk.alias) || cnode->global.inlined_to)
>  	continue;
> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
> +      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
>      }
> 
>    /* Write all variables.  */
>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>      {
> -      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      varpool_node *vnode = snode->try_variable ();
> +      if (!vnode)
>  	continue;
> -      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
>        if (DECL_EXTERNAL (vnode->symbol.decl))
>  	continue;
>        /* COMDAT virtual tables can be unshared.  Do not declare them
> -	 in the LTO symbol table to prevent linker from forcing them
> -	 into the output. */
> +	in the LTO symbol table to prevent linker from forcing them
> +	into the output. */
>        if (DECL_COMDAT (vnode->symbol.decl)
>  	  && !vnode->symbol.force_output
>  	  && vnode->finalized
> @@ -1356,9 +1355,10 @@ produce_symtab (struct output_block *ob)
>      }
>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>      {
> -      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      varpool_node *vnode = snode->try_variable ();
> +      if (!vnode)
>  	continue;
> -      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
>        if (!DECL_EXTERNAL (vnode->symbol.decl))
>  	continue;
>        if (DECL_COMDAT (vnode->symbol.decl)
> Index: gcc/ada/gcc-interface/utils.c
> ===================================================================
> --- gcc/ada/gcc-interface/utils.c	(revision 192010)
> +++ gcc/ada/gcc-interface/utils.c	(working copy)
> @@ -5582,7 +5582,7 @@ gnat_write_global_declarations (void)
>  		      void_type_node);
>        TREE_STATIC (dummy_global) = 1;
>        TREE_ASM_WRITTEN (dummy_global) = 1;
> -      node = varpool_node (dummy_global);
> +      node = varpool_node_for_decl (dummy_global);
>        node->symbol.force_output = 1;
> 
>        while (!VEC_empty (tree, types_used_by_cur_var_decl))
> Index: gcc/ipa.c
> ===================================================================
> --- gcc/ipa.c	(revision 192010)
> +++ gcc/ipa.c	(working copy)
> @@ -84,7 +84,7 @@ process_references (struct ipa_ref_list
>    struct ipa_ref *ref;
>    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
>      {
> -      if (symtab_function_p (ref->referred))
> +      if (ref->referred->is_function ())
>  	{
>  	  struct cgraph_node *node = ipa_ref_node (ref);
> 
> @@ -290,10 +290,8 @@ symtab_remove_unreachable_nodes (bool be
>  			      before_inlining_p, reachable);
>  	}
> 
> -      if (symtab_function_p (node))
> +      if (cgraph_node *cnode = node->try_function ())
>  	{
> -	  struct cgraph_node *cnode = cgraph (node);
> -
>  	  /* Mark the callees reachable unless they are direct calls to extern
>   	     inline functions we decided to not inline.  */
>  	  if (!in_boundary_p)
> @@ -332,18 +330,18 @@ symtab_remove_unreachable_nodes (bool be
>  	    }
>  	}
>        /* When we see constructor of external variable, keep referred
> nodes in the
> -	 boundary.  This will also hold initializers of the external vars NODE
> -	 reffers to.  */
> -      if (symtab_variable_p (node)
> +	boundary.  This will also hold initializers of the external vars NODE
> +	refers to.  */
> +      varpool_node *vnode = node->try_variable ();
> +      if (vnode
>  	  && DECL_EXTERNAL (node->symbol.decl)
> -	  && !varpool (node)->alias
> +	  && !vnode->alias
>  	  && in_boundary_p)
> -        {
> -	  int i;
> +	{
>  	  struct ipa_ref *ref;
> -	  for (i = 0; ipa_ref_list_reference_iterate
> (&node->symbol.ref_list, i, ref); i++)
> +	  for (int i = 0; ipa_ref_list_reference_iterate
> (&node->symbol.ref_list, i, ref); i++)
>  	    enqueue_node (ref->referred, &first, reachable);
> -        }
> +	}
>      }
> 
>    /* Remove unreachable functions.   */
> @@ -526,7 +524,7 @@ cgraph_address_taken_from_non_vtable_p (
>      if (ref->use == IPA_REF_ADDR)
>        {
>  	struct varpool_node *node;
> -	if (symtab_function_p (ref->referring))
> +	if (ref->referring->is_function ())
>  	  return true;
>  	node = ipa_ref_referring_varpool_node (ref);
>  	if (!DECL_VIRTUAL_P (node->symbol.decl))
> Index: gcc/ipa-inline-analysis.c
> ===================================================================
> --- gcc/ipa-inline-analysis.c	(revision 192010)
> +++ gcc/ipa-inline-analysis.c	(working copy)
> @@ -3811,22 +3811,25 @@ void
>  inline_write_summary (void)
>  {
>    struct cgraph_node *node;
> -  symtab_node snode;
>    struct output_block *ob = create_output_block (LTO_section_inline_summary);
>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>    unsigned int count = 0;
>    int i;
> 
>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
> -    if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder, i))
> -	&& cgraph (snode)->analyzed)
> -      count++;
> +    {
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      cgraph_node *cnode = snode->try_function ();
> +      if (cnode && cnode->analyzed)
> +	count++;
> +    }
>    streamer_write_uhwi (ob, count);
> 
>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>      {
> -      if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder, i))
> -	  && (node = cgraph (snode))->analyzed)
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      cgraph_node *cnode = snode->try_function ();
> +      if (cnode && (node = cnode)->analyzed)
>  	{
>  	  struct inline_summary *info = inline_summary (node);
>  	  struct bitpack_d bp;
> @@ -3834,7 +3837,7 @@ inline_write_summary (void)
>  	  int i;
>  	  size_time_entry *e;
>  	  struct condition *c;
> -
> +
>  	  streamer_write_uhwi (ob, lto_symtab_encoder_encode (encoder,
> (symtab_node)node));
>  	  streamer_write_hwi (ob, info->estimated_self_stack_size);
>  	  streamer_write_hwi (ob, info->self_size);
> @@ -3853,7 +3856,7 @@ inline_write_summary (void)
>  	      bp_pack_value (&bp, c->by_ref, 1);
>  	      streamer_write_bitpack (&bp);
>  	      if (c->agg_contents)
> -		streamer_write_uhwi (ob, c->offset);
> +	        streamer_write_uhwi (ob, c->offset);
>  	    }
>  	  streamer_write_uhwi (ob, VEC_length (size_time_entry, info->entry));
>  	  for (i = 0;
> Index: gcc/lto/lto.c
> ===================================================================
> --- gcc/lto/lto.c	(revision 192010)
> +++ gcc/lto/lto.c	(working copy)
> @@ -2620,12 +2620,17 @@ lto_wpa_write_files (void)
>  	      if (!lto_symtab_encoder_in_partition_p (part->encoder, node))
>  		{
>  	          fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name (node));
> -		  if (symtab_function_p (node)
> -		      && lto_symtab_encoder_encode_body_p (part->encoder, cgraph (node)))
> +		  cgraph_node *cnode = node->try_function ();
> +		  if (cnode
> +		      && lto_symtab_encoder_encode_body_p (part->encoder, cnode))
>  		    fprintf (cgraph_dump_file, "(body included)");
> -		  else if (symtab_variable_p (node)
> -		           && lto_symtab_encoder_encode_initializer_p
> (part->encoder, varpool (node)))
> -		    fprintf (cgraph_dump_file, "(initializer included)");
> +		  else
> +		    {
> +		      varpool_node *vnode = node->try_variable ();
> +		      if (vnode
> +			  && lto_symtab_encoder_encode_initializer_p (part->encoder, vnode))
> +			fprintf (cgraph_dump_file, "(initializer included)");
> +		    }
>  		}
>  	    }
>  	  fprintf (cgraph_dump_file, "\n");
> Index: gcc/lto/lto-partition.c
> ===================================================================
> --- gcc/lto/lto-partition.c	(revision 192010)
> +++ gcc/lto/lto-partition.c	(working copy)
> @@ -55,22 +55,22 @@ get_symbol_class (symtab_node node)
>  {
>    /* Inline clones are always duplicated.
>       This include external delcarations.   */
> -  if (symtab_function_p (node)
> -      && cgraph (node)->global.inlined_to)
> +  cgraph_node *cnode = node->try_function ();
> +  if (cnode && cnode->global.inlined_to)
>      return SYMBOL_DUPLICATE;
> 
>    /* External declarations are external.  */
>    if (DECL_EXTERNAL (node->symbol.decl))
>      return SYMBOL_EXTERNAL;
> 
> -  if (symtab_variable_p (node))
> +  if (varpool_node *vnode = node->try_variable ())
>      {
>        /* Constant pool references use local symbol names that can not
>           be promoted global.  We should never put into a constant pool
>           objects that can not be duplicated across partitions.  */
>        if (DECL_IN_CONSTANT_POOL (node->symbol.decl))
>  	return SYMBOL_DUPLICATE;
> -      gcc_checking_assert (varpool (node)->analyzed);
> +      gcc_checking_assert (vnode->analyzed);
>      }
>    /* Functions that are cloned may stay in callgraph even if they are unused.
>       Handle them as external; compute_ltrans_boundary take care to make
> @@ -145,7 +145,7 @@ add_references_to_partition (ltrans_part
>      /* References to a readonly variable may be constant foled into its value.
>         Recursively look into the initializers of the constant variable and add
>         references, too.  */
> -    else if (symtab_variable_p (ref->referred)
> +    else if (ref->referred->is_variable ()
>  	     && const_value_known_p (ref->referred->symbol.decl)
>  	     && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
>        {
> @@ -196,9 +196,8 @@ add_symbol_to_partition_1 (ltrans_partit
>      }
>    node->symbol.aux = (void *)((size_t)node->symbol.aux + 1);
> 
> -  if (symtab_function_p (node))
> +  if (cgraph_node *cnode = node->try_function ())
>      {
> -      struct cgraph_node *cnode = cgraph (node);
>        struct cgraph_edge *e;
>        part->insns += inline_summary (cnode)->self_size;
> 
> @@ -247,15 +246,15 @@ contained_in_symbol (symtab_node node)
>    if (lookup_attribute ("weakref",
>  			DECL_ATTRIBUTES (node->symbol.decl)))
>      return node;
> -  if (symtab_function_p (node))
> +  if (cgraph_node *cnode = node->try_function ())
>      {
> -      struct cgraph_node *cnode = cgraph_function_node (cgraph (node), NULL);
> +      cnode = cgraph_function_node (cnode, NULL);
>        if (cnode->global.inlined_to)
>  	cnode = cnode->global.inlined_to;
>        return (symtab_node) cnode;
>      }
> -  else if (symtab_variable_p (node))
> -    return (symtab_node) varpool_variable_node (varpool (node), NULL);
> +  else if (varpool_node *vnode = node->try_variable ())
> +    return (symtab_node) varpool_variable_node (vnode, NULL);
>    return node;
>  }
> 
> @@ -302,8 +301,8 @@ undo_partition (ltrans_partition partiti
>  	pointer_set_destroy (partition->initializers_visited);
>        partition->initializers_visited = NULL;
> 
> -      if (symtab_function_p (node))
> -        partition->insns -= inline_summary (cgraph (node))->self_size;
> +      if (cgraph_node *cnode = node->try_function ())
> +        partition->insns -= inline_summary (cnode)->self_size;
>        lto_symtab_encoder_delete_node (partition->encoder, node);
>        node->symbol.aux = (void *)((size_t)node->symbol.aux - 1);
>      }
> @@ -555,11 +554,10 @@ lto_balanced_map (void)
>  	  symtab_node snode = lto_symtab_encoder_deref (partition->encoder,
>  							last_visited_node);
> 
> -	  if (symtab_function_p (snode))
> +	  if (cgraph_node *node = snode->try_function ())
>  	    {
>  	      struct cgraph_edge *edge;
> 
> -	      node = cgraph (snode);
>  	      refs = &node->symbol.ref_list;
> 
>  	      last_visited_node++;
> @@ -611,7 +609,7 @@ lto_balanced_map (void)
>  	  /* Compute boundary cost of IPA REF edges and at the same time look into
>  	     variables referenced from current partition and try to add them.  */
>  	  for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++)
> -	    if (symtab_variable_p (ref->referred))
> +	    if (ref->referred->is_variable ())
>  	      {
>  		int index;
> 
> @@ -645,7 +643,7 @@ lto_balanced_map (void)
>  		  cost++;
>  	      }
>  	  for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++)
> -	    if (symtab_variable_p (ref->referring))
> +	    if (ref->referring->is_variable ())
>  	      {
>  		int index;
> 
> Index: gcc/varasm.c
> ===================================================================
> --- gcc/varasm.c	(revision 192010)
> +++ gcc/varasm.c	(working copy)
> @@ -2221,7 +2221,7 @@ mark_decl_referenced (tree decl)
>      }
>    else if (TREE_CODE (decl) == VAR_DECL)
>      {
> -      struct varpool_node *node = varpool_node (decl);
> +      struct varpool_node *node = varpool_node_for_decl (decl);
>        /* C++ frontend use mark_decl_references to force COMDAT variables
>           to be output that might appear dead otherwise.  */
>        node->symbol.force_output = true;
> @@ -5549,7 +5549,7 @@ assemble_alias (tree decl, tree target)
>    if (TREE_CODE (decl) == FUNCTION_DECL)
>      cgraph_get_create_node (decl)->alias = true;
>    else
> -    varpool_node (decl)->alias = true;
> +    varpool_node_for_decl (decl)->alias = true;
> 
>    /* If the target has already been emitted, we don't have to queue the
>       alias.  This saves a tad of memory.  */
> Index: gcc/symtab.c
> ===================================================================
> --- gcc/symtab.c	(revision 192010)
> +++ gcc/symtab.c	(working copy)
> @@ -104,7 +104,7 @@ eq_assembler_name (const void *p1, const
>  static void
>  insert_to_assembler_name_hash (symtab_node node)
>  {
> -  if (symtab_variable_p (node) && DECL_HARD_REGISTER (node->symbol.decl))
> +  if (node->is_variable () && DECL_HARD_REGISTER (node->symbol.decl))
>      return;
>    gcc_checking_assert (!node->symbol.previous_sharing_asm_name
>  		       && !node->symbol.next_sharing_asm_name);
> @@ -252,8 +252,8 @@ symtab_unregister_node (symtab_node node
>    if (*slot == node)
>      {
>        symtab_node replacement_node = NULL;
> -      if (symtab_function_p (node))
> -	replacement_node = (symtab_node)cgraph_find_replacement_node (cgraph (node));
> +      if (cgraph_node *cnode = node->try_function ())
> +	replacement_node = (symtab_node)cgraph_find_replacement_node (cnode);
>        if (!replacement_node)
>  	htab_clear_slot (symtab_hash, slot);
>        else
> @@ -294,10 +294,10 @@ symtab_get_node (const_tree decl)
>  void
>  symtab_remove_node (symtab_node node)
>  {
> -  if (symtab_function_p (node))
> -    cgraph_remove_node (cgraph (node));
> -  else if (symtab_variable_p (node))
> -    varpool_remove_node (varpool (node));
> +  if (cgraph_node *cnode = node->try_function ())
> +    cgraph_remove_node (cnode);
> +  else if (varpool_node *vnode = node->try_variable ())
> +    varpool_remove_node (vnode);
>  }
> 
>  /* Initalize asm name hash unless.  */
> @@ -538,10 +538,10 @@ dump_symtab_base (FILE *f, symtab_node n
>  void
>  dump_symtab_node (FILE *f, symtab_node node)
>  {
> -  if (symtab_function_p (node))
> -    dump_cgraph_node (f, cgraph (node));
> -  else if (symtab_variable_p (node))
> -    dump_varpool_node (f, varpool (node));
> +  if (cgraph_node *cnode = node->try_function ())
> +    dump_cgraph_node (f, cnode);
> +  else if (varpool_node *vnode = node->try_variable ())
> +    dump_varpool_node (f, vnode);
>  }
> 
>  /* Dump symbol table.  */
> @@ -579,7 +579,7 @@ verify_symtab_base (symtab_node node)
>    bool error_found = false;
>    symtab_node hashed_node;
> 
> -  if (symtab_function_p (node))
> +  if (node->is_function ())
>      {
>        if (TREE_CODE (node->symbol.decl) != FUNCTION_DECL)
>  	{
> @@ -587,7 +587,7 @@ verify_symtab_base (symtab_node node)
>            error_found = true;
>  	}
>      }
> -  else if (symtab_variable_p (node))
> +  else if (node->is_variable ())
>      {
>        if (TREE_CODE (node->symbol.decl) != VAR_DECL)
>  	{
> @@ -622,7 +622,7 @@ verify_symtab_base (symtab_node node)
>  	  hashed_node = hashed_node->symbol.next_sharing_asm_name;
>  	}
>        if (!hashed_node
> -          && !(symtab_variable_p (node) || DECL_HARD_REGISTER
> (node->symbol.decl)))
> +          && !(node->is_variable () || DECL_HARD_REGISTER (node->symbol.decl)))
>  	{
>            error ("node not found in symtab assembler name hash");
>            error_found = true;
> @@ -676,8 +676,8 @@ verify_symtab_node (symtab_node node)
>      return;
> 
>    timevar_push (TV_CGRAPH_VERIFY);
> -  if (symtab_function_p (node))
> -    verify_cgraph_node (cgraph (node));
> +  if (cgraph_node *cnode = node->try_function ())
> +    verify_cgraph_node (cnode);
>    else
>      if (verify_symtab_base (node))
>        {
> Index: gcc/passes.c
> ===================================================================
> --- gcc/passes.c	(revision 192010)
> +++ gcc/passes.c	(working copy)
> @@ -201,7 +201,7 @@ rest_of_decl_compilation (tree decl,
>      ;
>    else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)
>  	   && TREE_STATIC (decl))
> -    varpool_node (decl);
> +    varpool_node_for_decl (decl);
>  }
> 
>  /* Called after finishing a record, union or enumeral type.  */
> Index: gcc/varpool.c
> ===================================================================
> --- gcc/varpool.c	(revision 192010)
> +++ gcc/varpool.c	(working copy)
> @@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.
> 
>  /* Return varpool node assigned to DECL.  Create new one when needed.  */
>  struct varpool_node *
> -varpool_node (tree decl)
> +varpool_node_for_decl (tree decl)
>  {
>    struct varpool_node *node = varpool_get_node (decl);
>    gcc_assert (TREE_CODE (decl) == VAR_DECL
> @@ -114,9 +114,9 @@ debug_varpool (void)
>  struct varpool_node *
>  varpool_node_for_asm (tree asmname)
>  {
> -  symtab_node node = symtab_node_for_asm (asmname);
> -  if (node && symtab_variable_p (node))
> -    return varpool (node);
> +  if (symtab_node node = symtab_node_for_asm (asmname))
> +    if (varpool_node *vnode = node->try_variable ())
> +      return vnode;
>    return NULL;
>  }
> 
> @@ -192,7 +192,7 @@ varpool_add_new_variable (tree decl)
>  {
>    struct varpool_node *node;
>    varpool_finalize_decl (decl);
> -  node = varpool_node (decl);
> +  node = varpool_node_for_decl (decl);
>    if (varpool_externally_visible_p (node, false))
>      node->symbol.externally_visible = true;
>  }
> @@ -232,7 +232,7 @@ varpool_analyze_node (struct varpool_nod
>      }
>    if (node->alias && node->alias_of)
>      {
> -      struct varpool_node *tgt = varpool_node (node->alias_of);
> +      struct varpool_node *tgt = varpool_node_for_decl (node->alias_of);
>        struct varpool_node *n;
> 
>        for (n = tgt; n && n->alias;
> @@ -378,16 +378,21 @@ varpool_remove_unreferenced_decls (void)
>  	  for (next = node->symbol.same_comdat_group;
>  	       next != (symtab_node)node;
>  	       next = next->symbol.same_comdat_group)
> -	    if (symtab_variable_p (next)
> -		&& varpool (next)->analyzed)
> -	      enqueue_node (varpool (next), &first);
> +	    {
> +	      varpool_node *vnext = next->try_variable ();
> +	      if (vnext && vnext->analyzed)
> +		enqueue_node (vnext, &first);
> +	    }
>  	}
>        for (i = 0; ipa_ref_list_reference_iterate
> (&node->symbol.ref_list, i, ref); i++)
> -	if (symtab_variable_p (ref->referred)
> -	    && (!DECL_EXTERNAL (ref->referred->symbol.decl)
> -		|| varpool (ref->referred)->alias)
> -	    && varpool (ref->referred)->analyzed)
> -	  enqueue_node (varpool (ref->referred), &first);
> +	{
> +	  varpool_node *vnode = ref->referred->try_variable ();
> +	  if (vnode
> +	      && (!DECL_EXTERNAL (ref->referred->symbol.decl)
> +		  || vnode->alias)
> +	      && vnode->analyzed)
> +	    enqueue_node (vnode, &first);
> +	}
>      }
>    if (cgraph_dump_file)
>      fprintf (cgraph_dump_file, "\nRemoving variables:");
> @@ -461,7 +466,7 @@ add_new_static_var (tree type)
>    DECL_CONTEXT (new_decl) = NULL_TREE;
>    DECL_ABSTRACT (new_decl) = 0;
>    lang_hooks.dup_lang_specific_decl (new_decl);
> -  new_node = varpool_node (new_decl);
> +  new_node = varpool_node_for_decl (new_decl);
>    varpool_finalize_decl (new_decl);
> 
>    return new_node->symbol.decl;
> @@ -477,7 +482,7 @@ varpool_create_variable_alias (tree alia
> 
>    gcc_assert (TREE_CODE (decl) == VAR_DECL);
>    gcc_assert (TREE_CODE (alias) == VAR_DECL);
> -  alias_node = varpool_node (alias);
> +  alias_node = varpool_node_for_decl (alias);
>    alias_node->alias = 1;
>    alias_node->finalized = 1;
>    alias_node->alias_of = decl;
> Index: gcc/lto-streamer.h
> ===================================================================
> --- gcc/lto-streamer.h	(revision 192010)
> +++ gcc/lto-streamer.h	(working copy)
> @@ -1120,7 +1120,7 @@ lsei_next_function_in_partition (lto_sym
>  {
>    lsei_next (lsei);
>    while (!lsei_end_p (*lsei)
> -	 && (!symtab_function_p (lsei_node (*lsei))
> +	 && (!lsei_node (*lsei)->is_function ()
>  	     || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
> (*lsei))))
>      lsei_next (lsei);
>  }
> @@ -1133,7 +1133,7 @@ lsei_start_function_in_partition (lto_sy
> 
>    if (lsei_end_p (lsei))
>      return lsei;
> -  if (!symtab_function_p (lsei_node (lsei))
> +  if (!(lsei_node (lsei)->is_function ())
>        || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
>      lsei_next_function_in_partition (&lsei);
> 
> @@ -1146,7 +1146,7 @@ lsei_next_variable_in_partition (lto_sym
>  {
>    lsei_next (lsei);
>    while (!lsei_end_p (*lsei)
> -	 && (!symtab_variable_p (lsei_node (*lsei))
> +	 && (!lsei_node (*lsei)->is_variable ()
>  	     || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
> (*lsei))))
>      lsei_next (lsei);
>  }
> @@ -1159,7 +1159,7 @@ lsei_start_variable_in_partition (lto_sy
> 
>    if (lsei_end_p (lsei))
>      return lsei;
> -  if (!symtab_variable_p (lsei_node (lsei))
> +  if (!lsei_node (lsei)->is_variable ()
>        || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
>      lsei_next_variable_in_partition (&lsei);
> 
> 
> -- 
> Lawrence Crowl
Lawrence Crowl Oct. 3, 2012, 4:52 p.m. UTC | #2
On 10/3/12, Martin Jambor <mjambor@suse.cz> wrote:
> On Tue, Oct 02, 2012 at 05:32:38PM -0700, Lawrence Crowl wrote:
>> Updated Patch
>>
>> Add functions symtab_node_def::try_function and
>> symtab_node_def::try_variable.
>
> Even though I hate to be bikeshedding, I must say I really dislike the
> names, especially try_function.  Not only I believe it should be
> consistent with the name of the type it returns but, more importantly,
> it looks as if it had something to do with struct function which is an
> entirely different thing.
>
> I understand the names cgraph_node and varpool_node are slightly
> anachronistic in the symtab world, but still I think that they are
> perfectly usable, do not present a real obstacle to newcomers
> (cgraph_nodes do form the call graph, after all) and we are all used
> to them.  Therefore I'd be in favor of keeping them and changing the
> try_stuff function names accordingly.

These names were requested by Jan Hubicka to conform with
his planned type renaming.  So, your concern will be addressed
over time.

>> These function return a pointer to the more specific type (e.g.
>> cgraph_node*)
>> if and only if the general type (symtab_node aka symtab_node_def*) is an
>> instance of the specific type.  These functions are essentially checked
>> down
>> casts.
>>
>> These functions reduce compile time and increase type safety when treating
>> a
>> generic item as a more specific item.  In essence, the code change is
>> from
>>
>>   if (symtab_function_p (node))
>>     {
>>       struct cgraph_node *cnode = cgraph (node);
>>       ....
>>     }
>>
>> to
>>
>>   if (cgraph_node *cnode = node->try_function ())
>>     {
>>       ....
>>     }
>>
>> The necessary conditional test defines a variable that holds a known good
>> pointer to the specific item and avoids subsequent conversion calls and
>> the assertion checks that may come with them.
>>
>> When, the property test is embedded within a larger condition, the
>> variable
>> declaration gets pulled out of the condition.  (This leaves some room for
>> using the variable inappropriately.)
>>
>>   if (symtab_variable_p (node)
>>       && varpool (node)->finalized)
>>     varpool_analyze_node (varpool (node));
>>
>> becomes
>>
>>   varpool_node *vnode = node->try_variable ();
>>   if (vnode && vnode->finalized)
>>     varpool_analyze_node (vnode);
>>
>> Note that we have converted two sets of assertions in the calls to
>> varpool
>> into safe and efficient use of a variable.
>>
>>
>> There are remaining calls to symtab_function_p and symtab_variable_p that
>> do not involve a pointer to a more specific type.  These have been
>> converted
>> to calls to a member functions symtab_node_def::is_function and
>> symtab_node_def::is_variable.  The original predicate functions have been
>> removed.
>>
>>
>> The cgraph.h header defined both a struct and a function with the name
>> varpool_node.  This name overloading can cause some unintuitive error
>> messages
>> when, as is common in C++, one omits the struct keyword when using the
>> type.
>> I have renamed the function to varpool_node_for_decl.
>>
>>
>> The new code bootstraps .616% faster with a 99% confidence of being
>> faster.
>>
>>
>> Tested on x86_64.
>>
>>
>> Okay for trunk?
>>
>>
>> Index: gcc/ChangeLog
>>
>> 2012-10-02  Lawrence Crowl  <crowl@google.com
>>
>> 	* cgraph.h (varpool_node): Rename to varpool_node_for_decl.
>> 	Adjust callers to match.
>> 	(symtab_node_def::try_function): New.
>> 	Change most calls to symtab_function_p with calls to
>> 	symtab_node_def::try_function.
>> 	(symtab_node_def::try_variable): New.
>> 	Change most calls to symtab_variable_p with calls to
>> 	symtab_node_def::try_variable.
>> 	(symtab_function_p): Rename to symtab_node_def::is_function.
>> 	Adjust remaining callers to match.
>> 	(symtab_variable_p): Rename to symtab_node_def::is_variable.
>> 	Adjust remaining callers to match.
>> 	* cgraph.c (cgraph_node_for_asm): Remove redundant call to
>> 	symtab_node_for_asm.
>> 	* cgraphunit.c (symbol_finalized_and_needed): New.
>> 	(symbol_finalized): New.
>> 	(cgraph_analyze_functions): Split complicated conditionals out into
>> 	above new functions.
>>
>>
>> Index: gcc/lto-symtab.c
>> ===================================================================
>> --- gcc/lto-symtab.c	(revision 192010)
>> +++ gcc/lto-symtab.c	(working copy)
>> @@ -566,11 +566,11 @@ lto_symtab_merge_cgraph_nodes_1 (symtab_
>>
>>        if (!symtab_real_symbol_p (e))
>>  	continue;
>> -      if (symtab_function_p (e)
>> -	  && !DECL_BUILT_IN (e->symbol.decl))
>> -	lto_cgraph_replace_node (cgraph (e), cgraph (prevailing));
>> -      if (symtab_variable_p (e))
>> -	lto_varpool_replace_node (varpool (e), varpool (prevailing));
>> +      cgraph_node *ce = e->try_function ();
>> +      if (ce && !DECL_BUILT_IN (e->symbol.decl))
>> +	lto_cgraph_replace_node (ce, cgraph (prevailing));
>> +      if (varpool_node *ve = e->try_variable ())
>> +	lto_varpool_replace_node (ve, varpool (prevailing));
>>      }
>>
>>    return;
>> Index: gcc/cgraphbuild.c
>> ===================================================================
>> --- gcc/cgraphbuild.c	(revision 192010)
>> +++ gcc/cgraphbuild.c	(working copy)
>> @@ -84,7 +84,7 @@ record_reference (tree *tp, int *walk_su
>>
>>        if (TREE_CODE (decl) == VAR_DECL)
>>  	{
>> -	  struct varpool_node *vnode = varpool_node (decl);
>> +	  struct varpool_node *vnode = varpool_node_for_decl (decl);
>>  	  ipa_record_reference ((symtab_node)ctx->varpool_node,
>>  				(symtab_node)vnode,
>>  				IPA_REF_ADDR, NULL);
>> @@ -123,7 +123,7 @@ record_type_list (struct cgraph_node *no
>>  	  type = TREE_OPERAND (type, 0);
>>  	  if (TREE_CODE (type) == VAR_DECL)
>>  	    {
>> -	      struct varpool_node *vnode = varpool_node (type);
>> +	      struct varpool_node *vnode = varpool_node_for_decl (type);
>>  	      ipa_record_reference ((symtab_node)node,
>>  				    (symtab_node)vnode,
>>  				    IPA_REF_ADDR, NULL);
>> @@ -233,7 +233,7 @@ mark_address (gimple stmt, tree addr, vo
>>    else if (addr && TREE_CODE (addr) == VAR_DECL
>>  	   && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
>>      {
>> -      struct varpool_node *vnode = varpool_node (addr);
>> +      struct varpool_node *vnode = varpool_node_for_decl (addr);
>>
>>        ipa_record_reference ((symtab_node)data,
>>  			    (symtab_node)vnode,
>> @@ -262,7 +262,7 @@ mark_load (gimple stmt, tree t, void *da
>>    else if (t && TREE_CODE (t) == VAR_DECL
>>  	   && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
>>      {
>> -      struct varpool_node *vnode = varpool_node (t);
>> +      struct varpool_node *vnode = varpool_node_for_decl (t);
>>
>>        ipa_record_reference ((symtab_node)data,
>>  			    (symtab_node)vnode,
>> @@ -280,7 +280,7 @@ mark_store (gimple stmt, tree t, void *d
>>    if (t && TREE_CODE (t) == VAR_DECL
>>        && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
>>      {
>> -      struct varpool_node *vnode = varpool_node (t);
>> +      struct varpool_node *vnode = varpool_node_for_decl (t);
>>
>>        ipa_record_reference ((symtab_node)data,
>>  			    (symtab_node)vnode,
>> @@ -392,7 +392,7 @@ void
>>  record_references_in_initializer (tree decl, bool only_vars)
>>  {
>>    struct pointer_set_t *visited_nodes = pointer_set_create ();
>> -  struct varpool_node *node = varpool_node (decl);
>> +  struct varpool_node *node = varpool_node_for_decl (decl);
>>    struct record_reference_ctx ctx = {false, NULL};
>>
>>    ctx.varpool_node = node;
>> Index: gcc/cgraph.c
>> ===================================================================
>> --- gcc/cgraph.c	(revision 192010)
>> +++ gcc/cgraph.c	(working copy)
>> @@ -503,12 +503,15 @@ cgraph_add_thunk (struct cgraph_node *de
>>  struct cgraph_node *
>>  cgraph_node_for_asm (tree asmname)
>>  {
>> -  symtab_node node = symtab_node_for_asm (asmname);
>> -
>>    /* We do not want to look at inline clones.  */
>> -  for (node = symtab_node_for_asm (asmname); node; node =
>> node->symbol.next_sharing_asm_name)
>> -    if (symtab_function_p (node) && !cgraph(node)->global.inlined_to)
>> -      return cgraph (node);
>> +  for (symtab_node node = symtab_node_for_asm (asmname);
>> +       node;
>> +       node = node->symbol.next_sharing_asm_name)
>> +    {
>> +      cgraph_node *cn = node->try_function ();
>> +      if (cn && !cn->global.inlined_to)
>> +	return cn;
>> +    }
>>    return NULL;
>>  }
>>
>> Index: gcc/cgraph.h
>> ===================================================================
>> --- gcc/cgraph.h	(revision 192010)
>> +++ gcc/cgraph.h	(working copy)
>> @@ -456,13 +456,56 @@ struct GTY(()) asm_node {
>>  /* Symbol table entry.  */
>>  union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"),
>>  	   chain_prev ("%h.symbol.previous"))) symtab_node_def {
>> +  /* Dynamic type testers. */
>> +  bool GTY((skip)) is_function ();
>> +  bool GTY((skip)) is_variable ();
>> +  /* Conditional accessors return null if not the requested type.  */
>> +  cgraph_node * GTY((skip)) try_function ();
>> +  varpool_node * GTY((skip)) try_variable ();
>> +
>>    struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol;
>> -  /* Use cgraph (symbol) accessor to get cgraph_node.  */
>> +  /* To access the following fields,
>> +     use the conditional accessors try_function and try_variable above
>> +     or the asserting accessor functions cgraph and varpool.  */
>>    struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function;
>> -  /* Use varpool (symbol) accessor to get varpool_node.  */
>>    struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable;
>>  };
>>
>> +/* Report whether or not THIS symtab node is a function, aka cgraph_node.
>>  */
>> +
>> +inline bool
>> +symtab_node_def::is_function ()
>> +{
>> +  return symbol.type == SYMTAB_FUNCTION;
>> +}
>> +
>> +/* Report whether or not THIS symtab node is a vriable, aka varpool_node.
>>  */
>> +
>> +inline bool
>> +symtab_node_def::is_variable ()
>> +{
>> +  return symbol.type == SYMTAB_VARIABLE;
>> +}
>> +
>> +/* If THIS symtab node is a function, return a pointer to the
>> cgraph_node,
>> +   otherwise return NULL.  */
>> +
>> +inline cgraph_node *
>> +symtab_node_def::try_function ()
>> +{
>> +  return is_function () ? &x_function : NULL;
>> +}
>> +
>> +/* If THIS symtab node is a variable, return a pointer to the
>> varpool_node,
>> +   otherwise return NULL.  */
>> +
>> +inline varpool_node *
>> +symtab_node_def::try_variable()
>> +{
>> +  return is_variable () ? &x_variable : NULL;
>> +}
>> +
>> +
>>  extern GTY(()) symtab_node symtab_nodes;
>>  extern GTY(()) int cgraph_n_nodes;
>>  extern GTY(()) int cgraph_max_uid;
>> @@ -685,7 +728,7 @@ bool cgraph_maybe_hot_edge_p (struct cgr
>>  bool cgraph_optimize_for_size_p (struct cgraph_node *);
>>
>>  /* In varpool.c  */
>> -struct varpool_node *varpool_node (tree);
>> +struct varpool_node *varpool_node_for_decl (tree);
>>  struct varpool_node *varpool_node_for_asm (tree asmname);
>>  void varpool_mark_needed_node (struct varpool_node *);
>>  void debug_varpool (void);
>> @@ -715,19 +758,6 @@ void varpool_add_new_variable (tree);
>>  void symtab_initialize_asm_name_hash (void);
>>  void symtab_prevail_in_asm_name_hash (symtab_node node);
>>
>> -/* Return true when NODE is function.  */
>> -static inline bool
>> -symtab_function_p (symtab_node node)
>> -{
>> -  return node->symbol.type == SYMTAB_FUNCTION;
>> -}
>> -
>> -/* Return true when NODE is variable.  */
>> -static inline bool
>> -symtab_variable_p (symtab_node node)
>> -{
>> -  return node->symbol.type == SYMTAB_VARIABLE;
>> -}
>>
>>  /* Return callgraph node for given symbol and check it is a function. */
>>  static inline struct cgraph_node *
>> @@ -800,10 +830,8 @@ varpool_first_variable (void)
>>  {
>>    symtab_node node;
>>    for (node = symtab_nodes; node; node = node->symbol.next)
>> -    {
>> -      if (symtab_variable_p (node))
>> -	return varpool (node);
>> -    }
>> +    if (varpool_node *vnode = node->try_variable ())
>> +      return vnode;
>>    return NULL;
>>  }
>>
>> @@ -813,10 +841,8 @@ varpool_next_variable (struct varpool_no
>>  {
>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>    for (; node1; node1 = node1->symbol.next)
>> -    {
>> -      if (symtab_variable_p (node1))
>> -	return varpool (node1);
>> -    }
>> +    if (varpool_node *vnode1 = node1->try_variable ())
>> +      return vnode1;
>>    return NULL;
>>  }
>>  /* Walk all variables.  */
>> @@ -832,9 +858,9 @@ varpool_first_static_initializer (void)
>>    symtab_node node;
>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>      {
>> -      if (symtab_variable_p (node)
>> -	  && DECL_INITIAL (node->symbol.decl))
>> -	return varpool (node);
>> +      varpool_node *vnode = node->try_variable ();
>> +      if (vnode && DECL_INITIAL (node->symbol.decl))
>> +	return vnode;
>>      }
>>    return NULL;
>>  }
>> @@ -846,9 +872,9 @@ varpool_next_static_initializer (struct
>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>    for (; node1; node1 = node1->symbol.next)
>>      {
>> -      if (symtab_variable_p (node1)
>> -	  && DECL_INITIAL (node1->symbol.decl))
>> -	return varpool (node1);
>> +      varpool_node *vnode1 = node1->try_variable ();
>> +      if (vnode1 && DECL_INITIAL (node1->symbol.decl))
>> +	return vnode1;
>>      }
>>    return NULL;
>>  }
>> @@ -865,8 +891,9 @@ varpool_first_defined_variable (void)
>>    symtab_node node;
>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>      {
>> -      if (symtab_variable_p (node) && varpool (node)->analyzed)
>> -	return varpool (node);
>> +      varpool_node *vnode = node->try_variable ();
>> +      if (vnode && vnode->analyzed)
>> +	return vnode;
>>      }
>>    return NULL;
>>  }
>> @@ -878,8 +905,9 @@ varpool_next_defined_variable (struct va
>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>    for (; node1; node1 = node1->symbol.next)
>>      {
>> -      if (symtab_variable_p (node1) && varpool (node1)->analyzed)
>> -	return varpool (node1);
>> +      varpool_node *vnode1 = node1->try_variable ();
>> +      if (vnode1 && vnode1->analyzed)
>> +	return vnode1;
>>      }
>>    return NULL;
>>  }
>> @@ -895,8 +923,9 @@ cgraph_first_defined_function (void)
>>    symtab_node node;
>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>      {
>> -      if (symtab_function_p (node) && cgraph (node)->analyzed)
>> -	return cgraph (node);
>> +      cgraph_node *cn = node->try_function ();
>> +      if (cn && cn->analyzed)
>> +	return cn;
>>      }
>>    return NULL;
>>  }
>> @@ -908,8 +937,9 @@ cgraph_next_defined_function (struct cgr
>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>    for (; node1; node1 = node1->symbol.next)
>>      {
>> -      if (symtab_function_p (node1) && cgraph (node1)->analyzed)
>> -	return cgraph (node1);
>> +      cgraph_node *cn1 = node1->try_function ();
>> +      if (cn1 && cn1->analyzed)
>> +	return cn1;
>>      }
>>    return NULL;
>>  }
>> @@ -925,10 +955,8 @@ cgraph_first_function (void)
>>  {
>>    symtab_node node;
>>    for (node = symtab_nodes; node; node = node->symbol.next)
>> -    {
>> -      if (symtab_function_p (node))
>> -	return cgraph (node);
>> -    }
>> +    if (cgraph_node *cn = node->try_function ())
>> +      return cn;
>>    return NULL;
>>  }
>>
>> @@ -938,10 +966,8 @@ cgraph_next_function (struct cgraph_node
>>  {
>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>    for (; node1; node1 = node1->symbol.next)
>> -    {
>> -      if (symtab_function_p (node1))
>> -	return cgraph (node1);
>> -    }
>> +    if (cgraph_node *cn1 = node1->try_function ())
>> +      return cn1;
>>    return NULL;
>>  }
>>  /* Walk all functions.  */
>> @@ -968,9 +994,9 @@ cgraph_first_function_with_gimple_body (
>>    symtab_node node;
>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>      {
>> -      if (symtab_function_p (node)
>> -	  && cgraph_function_with_gimple_body_p (cgraph (node)))
>> -	return cgraph (node);
>> +      cgraph_node *cn = node->try_function ();
>> +      if (cn && cgraph_function_with_gimple_body_p (cn))
>> +	return cn;
>>      }
>>    return NULL;
>>  }
>> @@ -982,9 +1008,9 @@ cgraph_next_function_with_gimple_body (s
>>    symtab_node node1 = node->symbol.next;
>>    for (; node1; node1 = node1->symbol.next)
>>      {
>> -      if (symtab_function_p (node1)
>> -	  && cgraph_function_with_gimple_body_p (cgraph (node1)))
>> -	return cgraph (node1);
>> +      cgraph_node *cn1 = node1->try_function ();
>> +      if (cn1 && cgraph_function_with_gimple_body_p (cn1))
>> +	return cn1;
>>      }
>>    return NULL;
>>  }
>> @@ -1183,7 +1209,7 @@ cgraph_alias_aliased_node (struct cgraph
>>
>>    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
>>    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
>> -  if (symtab_function_p (ref->referred))
>> +  if (ref->referred->is_function ())
>>      return ipa_ref_node (ref);
>>    return NULL;
>>  }
>> @@ -1197,7 +1223,7 @@ varpool_alias_aliased_node (struct varpo
>>
>>    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
>>    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
>> -  if (symtab_variable_p (ref->referred))
>> +  if (ref->referred->is_variable ())
>>      return ipa_ref_varpool_node (ref);
>>    return NULL;
>>  }
>> @@ -1328,7 +1354,7 @@ symtab_real_symbol_p (symtab_node node)
>>    struct cgraph_node *cnode;
>>    struct ipa_ref *ref;
>>
>> -  if (!symtab_function_p (node))
>> +  if (!node->is_function ())
>>      return true;
>>    cnode = cgraph (node);
>>    if (cnode->global.inlined_to)
>> Index: gcc/tree-emutls.c
>> ===================================================================
>> --- gcc/tree-emutls.c	(revision 192010)
>> +++ gcc/tree-emutls.c	(working copy)
>> @@ -260,7 +260,7 @@ get_emutls_init_templ_addr (tree decl)
>>    /* Create varpool node for the new variable and finalize it if it is
>>       not external one.  */
>>    if (DECL_EXTERNAL (to))
>> -    varpool_node (to);
>> +    varpool_node_for_decl (to);
>>    else
>>      varpool_add_new_variable (to);
>>    return build_fold_addr_expr (to);
>> @@ -332,7 +332,7 @@ new_emutls_decl (tree decl, tree alias_o
>>    /* Create varpool node for the new variable and finalize it if it is
>>       not external one.  */
>>    if (DECL_EXTERNAL (to))
>> -    varpool_node (to);
>> +    varpool_node_for_decl (to);
>>    else if (!alias_of)
>>      varpool_add_new_variable (to);
>>    else
>> Index: gcc/ipa-reference.c
>> ===================================================================
>> --- gcc/ipa-reference.c	(revision 192010)
>> +++ gcc/ipa-reference.c	(working copy)
>> @@ -482,7 +482,7 @@ analyze_function (struct cgraph_node *fn
>>    local = init_function_info (fn);
>>    for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list,
>> i, ref); i++)
>>      {
>> -      if (!symtab_variable_p (ref->referred))
>> +      if (!ref->referred->is_variable ())
>>  	continue;
>>        var = ipa_ref_varpool_node (ref)->symbol.decl;
>>        if (!is_proper_for_analysis (var))
>> @@ -979,8 +979,6 @@ stream_out_bitmap (struct lto_simple_out
>>  static void
>>  ipa_reference_write_optimization_summary (void)
>>  {
>> -  struct cgraph_node *node;
>> -  symtab_node snode;
>>    struct lto_simple_output_block *ob
>>      = lto_create_simple_output_block (LTO_section_ipa_reference);
>>    unsigned int count = 0;
>> @@ -994,12 +992,10 @@ ipa_reference_write_optimization_summary
>>    /* See what variables we are interested in.  */
>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>      {
>> -      struct varpool_node *vnode;
>> -      snode = lto_symtab_encoder_deref (encoder, i);
>> -      if (!symtab_variable_p (snode))
>> -	continue;
>> -      vnode = varpool (snode);
>> -      if (bitmap_bit_p (all_module_statics, DECL_UID
>> (vnode->symbol.decl))
>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> +      varpool_node *vnode = snode->try_variable ();
>> +      if (vnode
>> +	  && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
>>  	  && referenced_from_this_partition_p (&vnode->symbol.ref_list,
>> encoder))
>>  	{
>>  	  tree decl = vnode->symbol.decl;
>> @@ -1013,10 +1009,12 @@ ipa_reference_write_optimization_summary
>>
>>    if (ltrans_statics_bitcount)
>>      for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>> -      if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder,
>> i))
>> -	  && write_node_summary_p (cgraph (snode),
>> -				   encoder, ltrans_statics))
>> +      {
>> +	symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> +	cgraph_node *cnode = snode->try_function ();
>> +	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
>>  	  count++;
>> +      }
>>
>>    streamer_write_uhwi_stream (ob->main_stream, count);
>>    if (count)
>> @@ -1027,17 +1025,15 @@ ipa_reference_write_optimization_summary
>>    if (ltrans_statics_bitcount)
>>      for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>        {
>> -	snode = lto_symtab_encoder_deref (encoder, i);
>> -	if (!symtab_function_p (snode))
>> -	  continue;
>> -	node = cgraph (snode);
>> -	if (write_node_summary_p (node, encoder, ltrans_statics))
>> +	symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> +	cgraph_node *cnode = snode->try_function ();
>> +	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
>>  	  {
>>  	    ipa_reference_optimization_summary_t info;
>>  	    int node_ref;
>>
>> -	    info = get_reference_optimization_summary (node);
>> -	    node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
>> +	    info = get_reference_optimization_summary (cnode);
>> +	    node_ref = lto_symtab_encoder_encode (encoder, snode);
>>  	    streamer_write_uhwi_stream (ob->main_stream, node_ref);
>>
>>  	    stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
>> Index: gcc/cgraphunit.c
>> ===================================================================
>> --- gcc/cgraphunit.c	(revision 192010)
>> +++ gcc/cgraphunit.c	(working copy)
>> @@ -386,7 +386,8 @@ referred_to_p (symtab_node node)
>>    if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
>>      return true;
>>    /* For functions check also calls.  */
>> -  if (symtab_function_p (node) && cgraph (node)->callers)
>> +  cgraph_node *cn = node->try_function ();
>> +  if (cn && cn->callers)
>>      return true;
>>    return false;
>>  }
>> @@ -809,7 +810,7 @@ process_function_and_variable_attributes
>>  void
>>  varpool_finalize_decl (tree decl)
>>  {
>> -  struct varpool_node *node = varpool_node (decl);
>> +  struct varpool_node *node = varpool_node_for_decl (decl);
>>
>>    gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
>>
>> @@ -836,6 +837,35 @@ varpool_finalize_decl (tree decl)
>>      varpool_assemble_decl (node);
>>  }
>>
>> +
>> +/* Determine if a symbol is finalized and needed.  */
>> +
>> +inline static bool
>> +symbol_finalized_and_needed (symtab_node node)
>> +{
>> +  if (cgraph_node *cnode = node->try_function ())
>> +    return cnode->local.finalized
>> +	   && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl);
>> +  if (varpool_node *vnode = node->try_variable ())
>> +    return vnode->finalized
>> +	   && !DECL_EXTERNAL (vnode->symbol.decl)
>> +	   && decide_is_variable_needed (vnode, vnode->symbol.decl);
>> +  return false;
>> +}
>> +
>> +/* Determine if a symbol is finalized.  */
>> +
>> +inline static bool
>> +symbol_finalized (symtab_node node)
>> +{
>> +  if (cgraph_node *cnode= node->try_function ())
>> +    return cnode->local.finalized;
>> +  if (varpool_node *vnode = node->try_variable ())
>> +    return vnode->finalized;
>> +  return false;
>> +}
>> +
>> +
>>  /* Discover all functions and variables that are trivially needed,
>> analyze
>>     them as well as all functions and variables referred by them  */
>>
>> @@ -870,13 +900,7 @@ cgraph_analyze_functions (void)
>>  	   node != (symtab_node)first_analyzed
>>  	   && node != (symtab_node)first_analyzed_var; node =
>> node->symbol.next)
>>  	{
>> -	  if ((symtab_function_p (node)
>> -	       && cgraph (node)->local.finalized
>> -	       && cgraph_decide_is_function_needed (cgraph (node),
>> node->symbol.decl))
>> -	      || (symtab_variable_p (node)
>> -		  && varpool (node)->finalized
>> -		  && !DECL_EXTERNAL (node->symbol.decl)
>> -		  && decide_is_variable_needed (varpool (node), node->symbol.decl)))
>> +	  if (symbol_finalized_and_needed (node))
>>  	    {
>>  	      enqueue_node (node);
>>  	      if (!changed && cgraph_dump_file)
>> @@ -903,18 +927,15 @@ cgraph_analyze_functions (void)
>>  	  changed = true;
>>  	  node = first;
>>  	  first = (symtab_node)first->symbol.aux;
>> -	  if (symtab_function_p (node) && cgraph (node)->local.finalized)
>> +	  cgraph_node *cnode = node->try_function ();
>> +	  if (cnode && cnode->local.finalized)
>>  	    {
>>  	      struct cgraph_edge *edge;
>> -	      struct cgraph_node *cnode;
>> -	      tree decl;
>> -
>> -	      cnode = cgraph (node);
>> -	      decl = cnode->symbol.decl;
>> +	      tree decl = cnode->symbol.decl;
>>
>> -	      /* ??? It is possible to create extern inline function and later
>> using
>> -		 weak alias attribute to kill its body. See
>> -		 gcc.c-torture/compile/20011119-1.c  */
>> +	      /* ??? It is possible to create extern inline function
>> +	      and later using weak alias attribute to kill its body.
>> +	      See gcc.c-torture/compile/20011119-1.c  */
>>  	      if (!DECL_STRUCT_FUNCTION (decl)
>>  		  && (!cnode->alias || !cnode->thunk.alias)
>>  		  && !cnode->thunk.thunk_p)
>> @@ -929,23 +950,25 @@ cgraph_analyze_functions (void)
>>
>>  	      for (edge = cnode->callees; edge; edge = edge->next_callee)
>>  		if (edge->callee->local.finalized)
>> -		  enqueue_node ((symtab_node)edge->callee);
>> +		   enqueue_node ((symtab_node)edge->callee);
>>
>> -	      /* 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.  */
>> +	      /* 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.  */
>>  	      if (DECL_ABSTRACT_ORIGIN (decl))
>>  		{
>> -		  struct cgraph_node *origin_node;
>> -		  origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
>> +		  struct cgraph_node *origin_node
>> +	    	  = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
>>  		  origin_node->abstract_and_needed = true;
>>  		}
>> -
>>  	    }
>> -	  else if (symtab_variable_p (node)
>> -		   && varpool (node)->finalized)
>> -	    varpool_analyze_node (varpool (node));
>> +	  else
>> +	    {
>> +	      varpool_node *vnode = node->try_variable ();
>> +	      if (vnode && vnode->finalized)
>> +		varpool_analyze_node (vnode);
>> +	    }
>>
>>  	  if (node->symbol.same_comdat_group)
>>  	    {
>> @@ -956,8 +979,7 @@ cgraph_analyze_functions (void)
>>  		enqueue_node (next);
>>  	    }
>>  	  for (i = 0; ipa_ref_list_reference_iterate
>> (&node->symbol.ref_list, i, ref); i++)
>> -	    if ((symtab_function_p (ref->referred) && cgraph
>> (ref->referred)->local.finalized)
>> -		|| (symtab_variable_p (ref->referred) && varpool
>> (ref->referred)->finalized))
>> +	    if (symbol_finalized (ref->referred))
>>  	      enqueue_node (ref->referred);
>>            cgraph_process_new_functions ();
>>  	}
>> @@ -985,10 +1007,9 @@ cgraph_analyze_functions (void)
>>  	  symtab_remove_node (node);
>>  	  continue;
>>  	}
>> -      if (symtab_function_p (node))
>> +      if (cgraph_node *cnode = node->try_function ())
>>  	{
>>  	  tree decl = node->symbol.decl;
>> -	  struct cgraph_node *cnode = cgraph (node);
>>
>>  	  if (cnode->local.finalized && !gimple_has_body_p (decl)
>>  	      && (!cnode->alias || !cnode->thunk.alias)
>> @@ -1070,7 +1091,7 @@ handle_alias_pairs (void)
>>  	}
>>
>>        if (TREE_CODE (p->decl) == FUNCTION_DECL
>> -          && target_node && symtab_function_p (target_node))
>> +          && target_node && target_node->is_function ())
>>  	{
>>  	  struct cgraph_node *src_node = cgraph_get_node (p->decl);
>>  	  if (src_node && src_node->local.finalized)
>> @@ -1079,7 +1100,7 @@ handle_alias_pairs (void)
>>  	  VEC_unordered_remove (alias_pair, alias_pairs, i);
>>  	}
>>        else if (TREE_CODE (p->decl) == VAR_DECL
>> -	       && target_node && symtab_variable_p (target_node))
>> +	       && target_node && target_node->is_variable ())
>>  	{
>>  	  varpool_create_variable_alias (p->decl, target_node->symbol.decl);
>>  	  VEC_unordered_remove (alias_pair, alias_pairs, i);
>> Index: gcc/cp/decl2.c
>> ===================================================================
>> --- gcc/cp/decl2.c	(revision 192010)
>> +++ gcc/cp/decl2.c	(working copy)
>> @@ -1778,7 +1778,7 @@ import_export_class (tree ctype)
>>  static bool
>>  var_finalized_p (tree var)
>>  {
>> -  return varpool_node (var)->finalized;
>> +  return varpool_node_for_decl (var)->finalized;
>>  }
>>
>>  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
>> @@ -1896,7 +1896,7 @@ maybe_emit_vtables (tree ctype)
>>  	TREE_ASM_WRITTEN (vtbl) = 1;
>>        else if (DECL_ONE_ONLY (vtbl))
>>  	{
>> -	  current = varpool_node (vtbl);
>> +	  current = varpool_node_for_decl (vtbl);
>>  	  if (last)
>>  	    symtab_add_to_same_comdat_group ((symtab_node) current,
>> (symtab_node) last);
>>  	  last = current;
>> Index: gcc/ipa-ref.c
>> ===================================================================
>> --- gcc/ipa-ref.c	(revision 192010)
>> +++ gcc/ipa-ref.c	(working copy)
>> @@ -42,7 +42,7 @@ ipa_record_reference (symtab_node referr
>>    struct ipa_ref_list *list, *list2;
>>    VEC(ipa_ref_t,gc) *old_references;
>>
>> -  gcc_checking_assert (!stmt || symtab_function_p (referring_node));
>> +  gcc_checking_assert (!stmt || referring_node->is_function ());
>>    gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
>>
>>    list = &referring_node->symbol.ref_list;
>> Index: gcc/lto-cgraph.c
>> ===================================================================
>> --- gcc/lto-cgraph.c	(revision 192010)
>> +++ gcc/lto-cgraph.c	(working copy)
>> @@ -665,7 +665,7 @@ add_references (lto_symtab_encoder_t enc
>>    int i;
>>    struct ipa_ref *ref;
>>    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
>> -    if (symtab_function_p (ref->referred))
>> +    if (ref->referred->is_function ())
>>        add_node_to (encoder, ipa_ref_node (ref), false);
>>      else
>>        lto_symtab_encoder_encode (encoder, ref->referred);
>> @@ -716,9 +716,8 @@ compute_ltrans_boundary (lto_symtab_enco
>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>      {
>>        symtab_node node = lto_symtab_encoder_deref (encoder, i);
>> -      if (symtab_variable_p (node))
>> +      if (varpool_node *vnode = node->try_variable ())
>>  	{
>> -	  struct varpool_node *vnode = varpool (node);
>>  	  if (DECL_INITIAL (vnode->symbol.decl)
>>  	      && !lto_symtab_encoder_encode_initializer_p (encoder,
>>  							   vnode)
>> @@ -782,8 +781,8 @@ output_symtab (void)
>>    for (i = 0; i < n_nodes; i++)
>>      {
>>        symtab_node node = lto_symtab_encoder_deref (encoder, i);
>> -      if (symtab_function_p (node))
>> -        lto_output_node (ob, cgraph (node), encoder);
>> +      if (cgraph_node *cnode = node->try_function ())
>> +        lto_output_node (ob, cnode, encoder);
>>        else
>>          lto_output_varpool_node (ob, varpool (node), encoder);
>>  	
>> @@ -969,7 +968,7 @@ input_varpool_node (struct lto_file_decl
>>    order = streamer_read_hwi (ib) + order_base;
>>    decl_index = streamer_read_uhwi (ib);
>>    var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
>> -  node = varpool_node (var_decl);
>> +  node = varpool_node_for_decl (var_decl);
>>    node->symbol.order = order;
>>    if (order >= symtab_order)
>>      symtab_order = order + 1;
>> @@ -1130,14 +1129,14 @@ input_cgraph_1 (struct lto_file_decl_dat
>>    /* AUX pointers should be all non-zero for function nodes read from
>> the stream.  */
>>  #ifdef ENABLE_CHECKING
>>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>> -    gcc_assert (node->symbol.aux || !symtab_function_p (node));
>> +    gcc_assert (node->symbol.aux || !node->is_function ());
>>  #endif
>>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>>      {
>>        int ref;
>> -      if (symtab_function_p (node))
>> +      if (cgraph_node *cnode = node->try_function ())
>>  	{
>> -	  ref = (int) (intptr_t) cgraph (node)->global.inlined_to;
>> +	  ref = (int) (intptr_t) cnode->global.inlined_to;
>>
>>  	  /* We share declaration of builtins, so we may read same node twice.
>> */
>>  	  if (!node->symbol.aux)
>> @@ -1146,9 +1145,9 @@ input_cgraph_1 (struct lto_file_decl_dat
>>
>>  	  /* Fixup inlined_to from reference to pointer.  */
>>  	  if (ref != LCC_NOT_FOUND)
>> -	    cgraph (node)->global.inlined_to = cgraph (VEC_index
>> (symtab_node, nodes, ref));
>> +	    cnode->global.inlined_to = cgraph (VEC_index (symtab_node, nodes,
>> ref));
>>  	  else
>> -	    cgraph (node)->global.inlined_to = NULL;
>> +	    cnode->global.inlined_to = NULL;
>>  	}
>>
>>        ref = (int) (intptr_t) node->symbol.same_comdat_group;
>> @@ -1160,7 +1159,7 @@ input_cgraph_1 (struct lto_file_decl_dat
>>  	node->symbol.same_comdat_group = NULL;
>>      }
>>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>> -    node->symbol.aux = symtab_function_p (node) ? (void *)1 : NULL;
>> +    node->symbol.aux = node->is_function () ? (void *)1 : NULL;
>>    return nodes;
>>  }
>>
>> @@ -1435,7 +1434,6 @@ output_node_opt_summary (struct output_b
>>  static void
>>  output_cgraph_opt_summary (void)
>>  {
>> -  symtab_node node;
>>    int i, n_nodes;
>>    lto_symtab_encoder_t encoder;
>>    struct output_block *ob = create_output_block
>> (LTO_section_cgraph_opt_sum);
>> @@ -1445,18 +1443,21 @@ output_cgraph_opt_summary (void)
>>    encoder = ob->decl_state->symtab_node_encoder;
>>    n_nodes = lto_symtab_encoder_size (encoder);
>>    for (i = 0; i < n_nodes; i++)
>> -    if (symtab_function_p (node = lto_symtab_encoder_deref (encoder, i))
>> -	&& output_cgraph_opt_summary_p (cgraph (node)))
>> -      count++;
>> +    {
>> +      symtab_node node = lto_symtab_encoder_deref (encoder, i);
>> +      cgraph_node *cnode = node->try_function ();
>> +      if (cnode && output_cgraph_opt_summary_p (cnode))
>> +	count++;
>> +    }
>>    streamer_write_uhwi (ob, count);
>>    for (i = 0; i < n_nodes; i++)
>>      {
>> -      node = lto_symtab_encoder_deref (encoder, i);
>> -      if (symtab_function_p (node)
>> -	  && output_cgraph_opt_summary_p (cgraph (node)))
>> +      symtab_node node = lto_symtab_encoder_deref (encoder, i);
>> +      cgraph_node *cnode = node->try_function ();
>> +      if (cnode && output_cgraph_opt_summary_p (cnode))
>>  	{
>>  	  streamer_write_uhwi (ob, i);
>> -	  output_node_opt_summary (ob, cgraph (node), encoder);
>> +	  output_node_opt_summary (ob, cnode, encoder);
>>  	}
>>      }
>>    produce_asm (ob, NULL);
>> Index: gcc/lto-streamer-out.c
>> ===================================================================
>> --- gcc/lto-streamer-out.c	(revision 192010)
>> +++ gcc/lto-streamer-out.c	(working copy)
>> @@ -972,7 +972,6 @@ copy_function (struct cgraph_node *node)
>>  static void
>>  lto_output (void)
>>  {
>> -  struct cgraph_node *node;
>>    struct lto_out_decl_state *decl_state;
>>  #ifdef ENABLE_CHECKING
>>    bitmap output = lto_bitmap_alloc ();
>> @@ -988,10 +987,9 @@ lto_output (void)
>>    for (i = 0; i < n_nodes; i++)
>>      {
>>        symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> -      if (!symtab_function_p (snode))
>> -	continue;
>> -      node = cgraph (snode);
>> -      if (lto_symtab_encoder_encode_body_p (encoder, node)
>> +      cgraph_node *node = snode->try_function ();
>> +      if (node
>> +	  && lto_symtab_encoder_encode_body_p (encoder, node)
>>  	  && !node->alias
>>  	  && !node->thunk.thunk_p)
>>  	{
>> @@ -1285,8 +1283,6 @@ produce_symtab (struct output_block *ob)
>>    struct streamer_tree_cache_d *cache = ob->writer_cache;
>>    char *section_name = lto_get_section_name (LTO_section_symtab, NULL,
>> NULL);
>>    struct pointer_set_t *seen;
>> -  struct cgraph_node *node;
>> -  struct varpool_node *vnode;
>>    struct lto_output_stream stream;
>>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>>    int i;
>> @@ -1302,49 +1298,52 @@ produce_symtab (struct output_block *ob)
>>       This is done so only to handle duplicated symbols in cgraph.  */
>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>      {
>> -      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> +      cgraph_node *cnode = snode->try_function ();
>> +      if (!cnode)
>>  	continue;
>> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
>> -      if (DECL_EXTERNAL (node->symbol.decl))
>> +      if (DECL_EXTERNAL (cnode->symbol.decl))
>>  	continue;
>> -      if (DECL_COMDAT (node->symbol.decl)
>> -	  && cgraph_comdat_can_be_unshared_p (node))
>> +      if (DECL_COMDAT (cnode->symbol.decl)
>> +	  && cgraph_comdat_can_be_unshared_p (cnode))
>>  	continue;
>> -      if ((node->alias && !node->thunk.alias) ||
>> node->global.inlined_to)
>> +      if ((cnode->alias && !cnode->thunk.alias) ||
>> cnode->global.inlined_to)
>>  	continue;
>> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
>> +      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
>>      }
>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>      {
>> -      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> +      cgraph_node *cnode = snode->try_function ();
>> +      if (!cnode)
>>  	continue;
>> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
>> -      if (!DECL_EXTERNAL (node->symbol.decl))
>> +      if (!DECL_EXTERNAL (cnode->symbol.decl))
>>  	continue;
>>        /* We keep around unused extern inlines in order to be able to
>> inline
>>  	 them indirectly or via vtables.  Do not output them to symbol
>>  	 table: they end up being undefined and just consume space.  */
>> -      if (!node->symbol.address_taken && !node->callers)
>> +      if (!cnode->symbol.address_taken && !cnode->callers)
>>  	continue;
>> -      if (DECL_COMDAT (node->symbol.decl)
>> -	  && cgraph_comdat_can_be_unshared_p (node))
>> +      if (DECL_COMDAT (cnode->symbol.decl)
>> +	  && cgraph_comdat_can_be_unshared_p (cnode))
>>  	continue;
>> -      if ((node->alias && !node->thunk.alias) ||
>> node->global.inlined_to)
>> +      if ((cnode->alias && !cnode->thunk.alias) ||
>> cnode->global.inlined_to)
>>  	continue;
>> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
>> +      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
>>      }
>>
>>    /* Write all variables.  */
>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>      {
>> -      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> +      varpool_node *vnode = snode->try_variable ();
>> +      if (!vnode)
>>  	continue;
>> -      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
>>        if (DECL_EXTERNAL (vnode->symbol.decl))
>>  	continue;
>>        /* COMDAT virtual tables can be unshared.  Do not declare them
>> -	 in the LTO symbol table to prevent linker from forcing them
>> -	 into the output. */
>> +	in the LTO symbol table to prevent linker from forcing them
>> +	into the output. */
>>        if (DECL_COMDAT (vnode->symbol.decl)
>>  	  && !vnode->symbol.force_output
>>  	  && vnode->finalized
>> @@ -1356,9 +1355,10 @@ produce_symtab (struct output_block *ob)
>>      }
>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>      {
>> -      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> +      varpool_node *vnode = snode->try_variable ();
>> +      if (!vnode)
>>  	continue;
>> -      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
>>        if (!DECL_EXTERNAL (vnode->symbol.decl))
>>  	continue;
>>        if (DECL_COMDAT (vnode->symbol.decl)
>> Index: gcc/ada/gcc-interface/utils.c
>> ===================================================================
>> --- gcc/ada/gcc-interface/utils.c	(revision 192010)
>> +++ gcc/ada/gcc-interface/utils.c	(working copy)
>> @@ -5582,7 +5582,7 @@ gnat_write_global_declarations (void)
>>  		      void_type_node);
>>        TREE_STATIC (dummy_global) = 1;
>>        TREE_ASM_WRITTEN (dummy_global) = 1;
>> -      node = varpool_node (dummy_global);
>> +      node = varpool_node_for_decl (dummy_global);
>>        node->symbol.force_output = 1;
>>
>>        while (!VEC_empty (tree, types_used_by_cur_var_decl))
>> Index: gcc/ipa.c
>> ===================================================================
>> --- gcc/ipa.c	(revision 192010)
>> +++ gcc/ipa.c	(working copy)
>> @@ -84,7 +84,7 @@ process_references (struct ipa_ref_list
>>    struct ipa_ref *ref;
>>    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
>>      {
>> -      if (symtab_function_p (ref->referred))
>> +      if (ref->referred->is_function ())
>>  	{
>>  	  struct cgraph_node *node = ipa_ref_node (ref);
>>
>> @@ -290,10 +290,8 @@ symtab_remove_unreachable_nodes (bool be
>>  			      before_inlining_p, reachable);
>>  	}
>>
>> -      if (symtab_function_p (node))
>> +      if (cgraph_node *cnode = node->try_function ())
>>  	{
>> -	  struct cgraph_node *cnode = cgraph (node);
>> -
>>  	  /* Mark the callees reachable unless they are direct calls to extern
>>   	     inline functions we decided to not inline.  */
>>  	  if (!in_boundary_p)
>> @@ -332,18 +330,18 @@ symtab_remove_unreachable_nodes (bool be
>>  	    }
>>  	}
>>        /* When we see constructor of external variable, keep referred
>> nodes in the
>> -	 boundary.  This will also hold initializers of the external vars NODE
>> -	 reffers to.  */
>> -      if (symtab_variable_p (node)
>> +	boundary.  This will also hold initializers of the external vars NODE
>> +	refers to.  */
>> +      varpool_node *vnode = node->try_variable ();
>> +      if (vnode
>>  	  && DECL_EXTERNAL (node->symbol.decl)
>> -	  && !varpool (node)->alias
>> +	  && !vnode->alias
>>  	  && in_boundary_p)
>> -        {
>> -	  int i;
>> +	{
>>  	  struct ipa_ref *ref;
>> -	  for (i = 0; ipa_ref_list_reference_iterate
>> (&node->symbol.ref_list, i, ref); i++)
>> +	  for (int i = 0; ipa_ref_list_reference_iterate
>> (&node->symbol.ref_list, i, ref); i++)
>>  	    enqueue_node (ref->referred, &first, reachable);
>> -        }
>> +	}
>>      }
>>
>>    /* Remove unreachable functions.   */
>> @@ -526,7 +524,7 @@ cgraph_address_taken_from_non_vtable_p (
>>      if (ref->use == IPA_REF_ADDR)
>>        {
>>  	struct varpool_node *node;
>> -	if (symtab_function_p (ref->referring))
>> +	if (ref->referring->is_function ())
>>  	  return true;
>>  	node = ipa_ref_referring_varpool_node (ref);
>>  	if (!DECL_VIRTUAL_P (node->symbol.decl))
>> Index: gcc/ipa-inline-analysis.c
>> ===================================================================
>> --- gcc/ipa-inline-analysis.c	(revision 192010)
>> +++ gcc/ipa-inline-analysis.c	(working copy)
>> @@ -3811,22 +3811,25 @@ void
>>  inline_write_summary (void)
>>  {
>>    struct cgraph_node *node;
>> -  symtab_node snode;
>>    struct output_block *ob = create_output_block
>> (LTO_section_inline_summary);
>>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>>    unsigned int count = 0;
>>    int i;
>>
>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>> -    if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder,
>> i))
>> -	&& cgraph (snode)->analyzed)
>> -      count++;
>> +    {
>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> +      cgraph_node *cnode = snode->try_function ();
>> +      if (cnode && cnode->analyzed)
>> +	count++;
>> +    }
>>    streamer_write_uhwi (ob, count);
>>
>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>      {
>> -      if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder,
>> i))
>> -	  && (node = cgraph (snode))->analyzed)
>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>> +      cgraph_node *cnode = snode->try_function ();
>> +      if (cnode && (node = cnode)->analyzed)
>>  	{
>>  	  struct inline_summary *info = inline_summary (node);
>>  	  struct bitpack_d bp;
>> @@ -3834,7 +3837,7 @@ inline_write_summary (void)
>>  	  int i;
>>  	  size_time_entry *e;
>>  	  struct condition *c;
>> -
>> +
>>  	  streamer_write_uhwi (ob, lto_symtab_encoder_encode (encoder,
>> (symtab_node)node));
>>  	  streamer_write_hwi (ob, info->estimated_self_stack_size);
>>  	  streamer_write_hwi (ob, info->self_size);
>> @@ -3853,7 +3856,7 @@ inline_write_summary (void)
>>  	      bp_pack_value (&bp, c->by_ref, 1);
>>  	      streamer_write_bitpack (&bp);
>>  	      if (c->agg_contents)
>> -		streamer_write_uhwi (ob, c->offset);
>> +	        streamer_write_uhwi (ob, c->offset);
>>  	    }
>>  	  streamer_write_uhwi (ob, VEC_length (size_time_entry, info->entry));
>>  	  for (i = 0;
>> Index: gcc/lto/lto.c
>> ===================================================================
>> --- gcc/lto/lto.c	(revision 192010)
>> +++ gcc/lto/lto.c	(working copy)
>> @@ -2620,12 +2620,17 @@ lto_wpa_write_files (void)
>>  	      if (!lto_symtab_encoder_in_partition_p (part->encoder, node))
>>  		{
>>  	          fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name
>> (node));
>> -		  if (symtab_function_p (node)
>> -		      && lto_symtab_encoder_encode_body_p (part->encoder, cgraph
>> (node)))
>> +		  cgraph_node *cnode = node->try_function ();
>> +		  if (cnode
>> +		      && lto_symtab_encoder_encode_body_p (part->encoder, cnode))
>>  		    fprintf (cgraph_dump_file, "(body included)");
>> -		  else if (symtab_variable_p (node)
>> -		           && lto_symtab_encoder_encode_initializer_p
>> (part->encoder, varpool (node)))
>> -		    fprintf (cgraph_dump_file, "(initializer included)");
>> +		  else
>> +		    {
>> +		      varpool_node *vnode = node->try_variable ();
>> +		      if (vnode
>> +			  && lto_symtab_encoder_encode_initializer_p (part->encoder, vnode))
>> +			fprintf (cgraph_dump_file, "(initializer included)");
>> +		    }
>>  		}
>>  	    }
>>  	  fprintf (cgraph_dump_file, "\n");
>> Index: gcc/lto/lto-partition.c
>> ===================================================================
>> --- gcc/lto/lto-partition.c	(revision 192010)
>> +++ gcc/lto/lto-partition.c	(working copy)
>> @@ -55,22 +55,22 @@ get_symbol_class (symtab_node node)
>>  {
>>    /* Inline clones are always duplicated.
>>       This include external delcarations.   */
>> -  if (symtab_function_p (node)
>> -      && cgraph (node)->global.inlined_to)
>> +  cgraph_node *cnode = node->try_function ();
>> +  if (cnode && cnode->global.inlined_to)
>>      return SYMBOL_DUPLICATE;
>>
>>    /* External declarations are external.  */
>>    if (DECL_EXTERNAL (node->symbol.decl))
>>      return SYMBOL_EXTERNAL;
>>
>> -  if (symtab_variable_p (node))
>> +  if (varpool_node *vnode = node->try_variable ())
>>      {
>>        /* Constant pool references use local symbol names that can not
>>           be promoted global.  We should never put into a constant pool
>>           objects that can not be duplicated across partitions.  */
>>        if (DECL_IN_CONSTANT_POOL (node->symbol.decl))
>>  	return SYMBOL_DUPLICATE;
>> -      gcc_checking_assert (varpool (node)->analyzed);
>> +      gcc_checking_assert (vnode->analyzed);
>>      }
>>    /* Functions that are cloned may stay in callgraph even if they are
>> unused.
>>       Handle them as external; compute_ltrans_boundary take care to make
>> @@ -145,7 +145,7 @@ add_references_to_partition (ltrans_part
>>      /* References to a readonly variable may be constant foled into its
>> value.
>>         Recursively look into the initializers of the constant variable
>> and add
>>         references, too.  */
>> -    else if (symtab_variable_p (ref->referred)
>> +    else if (ref->referred->is_variable ()
>>  	     && const_value_known_p (ref->referred->symbol.decl)
>>  	     && !lto_symtab_encoder_in_partition_p (part->encoder,
>> ref->referred))
>>        {
>> @@ -196,9 +196,8 @@ add_symbol_to_partition_1 (ltrans_partit
>>      }
>>    node->symbol.aux = (void *)((size_t)node->symbol.aux + 1);
>>
>> -  if (symtab_function_p (node))
>> +  if (cgraph_node *cnode = node->try_function ())
>>      {
>> -      struct cgraph_node *cnode = cgraph (node);
>>        struct cgraph_edge *e;
>>        part->insns += inline_summary (cnode)->self_size;
>>
>> @@ -247,15 +246,15 @@ contained_in_symbol (symtab_node node)
>>    if (lookup_attribute ("weakref",
>>  			DECL_ATTRIBUTES (node->symbol.decl)))
>>      return node;
>> -  if (symtab_function_p (node))
>> +  if (cgraph_node *cnode = node->try_function ())
>>      {
>> -      struct cgraph_node *cnode = cgraph_function_node (cgraph (node),
>> NULL);
>> +      cnode = cgraph_function_node (cnode, NULL);
>>        if (cnode->global.inlined_to)
>>  	cnode = cnode->global.inlined_to;
>>        return (symtab_node) cnode;
>>      }
>> -  else if (symtab_variable_p (node))
>> -    return (symtab_node) varpool_variable_node (varpool (node), NULL);
>> +  else if (varpool_node *vnode = node->try_variable ())
>> +    return (symtab_node) varpool_variable_node (vnode, NULL);
>>    return node;
>>  }
>>
>> @@ -302,8 +301,8 @@ undo_partition (ltrans_partition partiti
>>  	pointer_set_destroy (partition->initializers_visited);
>>        partition->initializers_visited = NULL;
>>
>> -      if (symtab_function_p (node))
>> -        partition->insns -= inline_summary (cgraph (node))->self_size;
>> +      if (cgraph_node *cnode = node->try_function ())
>> +        partition->insns -= inline_summary (cnode)->self_size;
>>        lto_symtab_encoder_delete_node (partition->encoder, node);
>>        node->symbol.aux = (void *)((size_t)node->symbol.aux - 1);
>>      }
>> @@ -555,11 +554,10 @@ lto_balanced_map (void)
>>  	  symtab_node snode = lto_symtab_encoder_deref (partition->encoder,
>>  							last_visited_node);
>>
>> -	  if (symtab_function_p (snode))
>> +	  if (cgraph_node *node = snode->try_function ())
>>  	    {
>>  	      struct cgraph_edge *edge;
>>
>> -	      node = cgraph (snode);
>>  	      refs = &node->symbol.ref_list;
>>
>>  	      last_visited_node++;
>> @@ -611,7 +609,7 @@ lto_balanced_map (void)
>>  	  /* Compute boundary cost of IPA REF edges and at the same time look
>> into
>>  	     variables referenced from current partition and try to add them.
>> */
>>  	  for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++)
>> -	    if (symtab_variable_p (ref->referred))
>> +	    if (ref->referred->is_variable ())
>>  	      {
>>  		int index;
>>
>> @@ -645,7 +643,7 @@ lto_balanced_map (void)
>>  		  cost++;
>>  	      }
>>  	  for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++)
>> -	    if (symtab_variable_p (ref->referring))
>> +	    if (ref->referring->is_variable ())
>>  	      {
>>  		int index;
>>
>> Index: gcc/varasm.c
>> ===================================================================
>> --- gcc/varasm.c	(revision 192010)
>> +++ gcc/varasm.c	(working copy)
>> @@ -2221,7 +2221,7 @@ mark_decl_referenced (tree decl)
>>      }
>>    else if (TREE_CODE (decl) == VAR_DECL)
>>      {
>> -      struct varpool_node *node = varpool_node (decl);
>> +      struct varpool_node *node = varpool_node_for_decl (decl);
>>        /* C++ frontend use mark_decl_references to force COMDAT variables
>>           to be output that might appear dead otherwise.  */
>>        node->symbol.force_output = true;
>> @@ -5549,7 +5549,7 @@ assemble_alias (tree decl, tree target)
>>    if (TREE_CODE (decl) == FUNCTION_DECL)
>>      cgraph_get_create_node (decl)->alias = true;
>>    else
>> -    varpool_node (decl)->alias = true;
>> +    varpool_node_for_decl (decl)->alias = true;
>>
>>    /* If the target has already been emitted, we don't have to queue the
>>       alias.  This saves a tad of memory.  */
>> Index: gcc/symtab.c
>> ===================================================================
>> --- gcc/symtab.c	(revision 192010)
>> +++ gcc/symtab.c	(working copy)
>> @@ -104,7 +104,7 @@ eq_assembler_name (const void *p1, const
>>  static void
>>  insert_to_assembler_name_hash (symtab_node node)
>>  {
>> -  if (symtab_variable_p (node) && DECL_HARD_REGISTER
>> (node->symbol.decl))
>> +  if (node->is_variable () && DECL_HARD_REGISTER (node->symbol.decl))
>>      return;
>>    gcc_checking_assert (!node->symbol.previous_sharing_asm_name
>>  		       && !node->symbol.next_sharing_asm_name);
>> @@ -252,8 +252,8 @@ symtab_unregister_node (symtab_node node
>>    if (*slot == node)
>>      {
>>        symtab_node replacement_node = NULL;
>> -      if (symtab_function_p (node))
>> -	replacement_node = (symtab_node)cgraph_find_replacement_node (cgraph
>> (node));
>> +      if (cgraph_node *cnode = node->try_function ())
>> +	replacement_node = (symtab_node)cgraph_find_replacement_node (cnode);
>>        if (!replacement_node)
>>  	htab_clear_slot (symtab_hash, slot);
>>        else
>> @@ -294,10 +294,10 @@ symtab_get_node (const_tree decl)
>>  void
>>  symtab_remove_node (symtab_node node)
>>  {
>> -  if (symtab_function_p (node))
>> -    cgraph_remove_node (cgraph (node));
>> -  else if (symtab_variable_p (node))
>> -    varpool_remove_node (varpool (node));
>> +  if (cgraph_node *cnode = node->try_function ())
>> +    cgraph_remove_node (cnode);
>> +  else if (varpool_node *vnode = node->try_variable ())
>> +    varpool_remove_node (vnode);
>>  }
>>
>>  /* Initalize asm name hash unless.  */
>> @@ -538,10 +538,10 @@ dump_symtab_base (FILE *f, symtab_node n
>>  void
>>  dump_symtab_node (FILE *f, symtab_node node)
>>  {
>> -  if (symtab_function_p (node))
>> -    dump_cgraph_node (f, cgraph (node));
>> -  else if (symtab_variable_p (node))
>> -    dump_varpool_node (f, varpool (node));
>> +  if (cgraph_node *cnode = node->try_function ())
>> +    dump_cgraph_node (f, cnode);
>> +  else if (varpool_node *vnode = node->try_variable ())
>> +    dump_varpool_node (f, vnode);
>>  }
>>
>>  /* Dump symbol table.  */
>> @@ -579,7 +579,7 @@ verify_symtab_base (symtab_node node)
>>    bool error_found = false;
>>    symtab_node hashed_node;
>>
>> -  if (symtab_function_p (node))
>> +  if (node->is_function ())
>>      {
>>        if (TREE_CODE (node->symbol.decl) != FUNCTION_DECL)
>>  	{
>> @@ -587,7 +587,7 @@ verify_symtab_base (symtab_node node)
>>            error_found = true;
>>  	}
>>      }
>> -  else if (symtab_variable_p (node))
>> +  else if (node->is_variable ())
>>      {
>>        if (TREE_CODE (node->symbol.decl) != VAR_DECL)
>>  	{
>> @@ -622,7 +622,7 @@ verify_symtab_base (symtab_node node)
>>  	  hashed_node = hashed_node->symbol.next_sharing_asm_name;
>>  	}
>>        if (!hashed_node
>> -          && !(symtab_variable_p (node) || DECL_HARD_REGISTER
>> (node->symbol.decl)))
>> +          && !(node->is_variable () || DECL_HARD_REGISTER
>> (node->symbol.decl)))
>>  	{
>>            error ("node not found in symtab assembler name hash");
>>            error_found = true;
>> @@ -676,8 +676,8 @@ verify_symtab_node (symtab_node node)
>>      return;
>>
>>    timevar_push (TV_CGRAPH_VERIFY);
>> -  if (symtab_function_p (node))
>> -    verify_cgraph_node (cgraph (node));
>> +  if (cgraph_node *cnode = node->try_function ())
>> +    verify_cgraph_node (cnode);
>>    else
>>      if (verify_symtab_base (node))
>>        {
>> Index: gcc/passes.c
>> ===================================================================
>> --- gcc/passes.c	(revision 192010)
>> +++ gcc/passes.c	(working copy)
>> @@ -201,7 +201,7 @@ rest_of_decl_compilation (tree decl,
>>      ;
>>    else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)
>>  	   && TREE_STATIC (decl))
>> -    varpool_node (decl);
>> +    varpool_node_for_decl (decl);
>>  }
>>
>>  /* Called after finishing a record, union or enumeral type.  */
>> Index: gcc/varpool.c
>> ===================================================================
>> --- gcc/varpool.c	(revision 192010)
>> +++ gcc/varpool.c	(working copy)
>> @@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.
>>
>>  /* Return varpool node assigned to DECL.  Create new one when needed.
>> */
>>  struct varpool_node *
>> -varpool_node (tree decl)
>> +varpool_node_for_decl (tree decl)
>>  {
>>    struct varpool_node *node = varpool_get_node (decl);
>>    gcc_assert (TREE_CODE (decl) == VAR_DECL
>> @@ -114,9 +114,9 @@ debug_varpool (void)
>>  struct varpool_node *
>>  varpool_node_for_asm (tree asmname)
>>  {
>> -  symtab_node node = symtab_node_for_asm (asmname);
>> -  if (node && symtab_variable_p (node))
>> -    return varpool (node);
>> +  if (symtab_node node = symtab_node_for_asm (asmname))
>> +    if (varpool_node *vnode = node->try_variable ())
>> +      return vnode;
>>    return NULL;
>>  }
>>
>> @@ -192,7 +192,7 @@ varpool_add_new_variable (tree decl)
>>  {
>>    struct varpool_node *node;
>>    varpool_finalize_decl (decl);
>> -  node = varpool_node (decl);
>> +  node = varpool_node_for_decl (decl);
>>    if (varpool_externally_visible_p (node, false))
>>      node->symbol.externally_visible = true;
>>  }
>> @@ -232,7 +232,7 @@ varpool_analyze_node (struct varpool_nod
>>      }
>>    if (node->alias && node->alias_of)
>>      {
>> -      struct varpool_node *tgt = varpool_node (node->alias_of);
>> +      struct varpool_node *tgt = varpool_node_for_decl (node->alias_of);
>>        struct varpool_node *n;
>>
>>        for (n = tgt; n && n->alias;
>> @@ -378,16 +378,21 @@ varpool_remove_unreferenced_decls (void)
>>  	  for (next = node->symbol.same_comdat_group;
>>  	       next != (symtab_node)node;
>>  	       next = next->symbol.same_comdat_group)
>> -	    if (symtab_variable_p (next)
>> -		&& varpool (next)->analyzed)
>> -	      enqueue_node (varpool (next), &first);
>> +	    {
>> +	      varpool_node *vnext = next->try_variable ();
>> +	      if (vnext && vnext->analyzed)
>> +		enqueue_node (vnext, &first);
>> +	    }
>>  	}
>>        for (i = 0; ipa_ref_list_reference_iterate
>> (&node->symbol.ref_list, i, ref); i++)
>> -	if (symtab_variable_p (ref->referred)
>> -	    && (!DECL_EXTERNAL (ref->referred->symbol.decl)
>> -		|| varpool (ref->referred)->alias)
>> -	    && varpool (ref->referred)->analyzed)
>> -	  enqueue_node (varpool (ref->referred), &first);
>> +	{
>> +	  varpool_node *vnode = ref->referred->try_variable ();
>> +	  if (vnode
>> +	      && (!DECL_EXTERNAL (ref->referred->symbol.decl)
>> +		  || vnode->alias)
>> +	      && vnode->analyzed)
>> +	    enqueue_node (vnode, &first);
>> +	}
>>      }
>>    if (cgraph_dump_file)
>>      fprintf (cgraph_dump_file, "\nRemoving variables:");
>> @@ -461,7 +466,7 @@ add_new_static_var (tree type)
>>    DECL_CONTEXT (new_decl) = NULL_TREE;
>>    DECL_ABSTRACT (new_decl) = 0;
>>    lang_hooks.dup_lang_specific_decl (new_decl);
>> -  new_node = varpool_node (new_decl);
>> +  new_node = varpool_node_for_decl (new_decl);
>>    varpool_finalize_decl (new_decl);
>>
>>    return new_node->symbol.decl;
>> @@ -477,7 +482,7 @@ varpool_create_variable_alias (tree alia
>>
>>    gcc_assert (TREE_CODE (decl) == VAR_DECL);
>>    gcc_assert (TREE_CODE (alias) == VAR_DECL);
>> -  alias_node = varpool_node (alias);
>> +  alias_node = varpool_node_for_decl (alias);
>>    alias_node->alias = 1;
>>    alias_node->finalized = 1;
>>    alias_node->alias_of = decl;
>> Index: gcc/lto-streamer.h
>> ===================================================================
>> --- gcc/lto-streamer.h	(revision 192010)
>> +++ gcc/lto-streamer.h	(working copy)
>> @@ -1120,7 +1120,7 @@ lsei_next_function_in_partition (lto_sym
>>  {
>>    lsei_next (lsei);
>>    while (!lsei_end_p (*lsei)
>> -	 && (!symtab_function_p (lsei_node (*lsei))
>> +	 && (!lsei_node (*lsei)->is_function ()
>>  	     || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
>> (*lsei))))
>>      lsei_next (lsei);
>>  }
>> @@ -1133,7 +1133,7 @@ lsei_start_function_in_partition (lto_sy
>>
>>    if (lsei_end_p (lsei))
>>      return lsei;
>> -  if (!symtab_function_p (lsei_node (lsei))
>> +  if (!(lsei_node (lsei)->is_function ())
>>        || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
>>      lsei_next_function_in_partition (&lsei);
>>
>> @@ -1146,7 +1146,7 @@ lsei_next_variable_in_partition (lto_sym
>>  {
>>    lsei_next (lsei);
>>    while (!lsei_end_p (*lsei)
>> -	 && (!symtab_variable_p (lsei_node (*lsei))
>> +	 && (!lsei_node (*lsei)->is_variable ()
>>  	     || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
>> (*lsei))))
>>      lsei_next (lsei);
>>  }
>> @@ -1159,7 +1159,7 @@ lsei_start_variable_in_partition (lto_sy
>>
>>    if (lsei_end_p (lsei))
>>      return lsei;
>> -  if (!symtab_variable_p (lsei_node (lsei))
>> +  if (!lsei_node (lsei)->is_variable ()
>>        || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
>>      lsei_next_variable_in_partition (&lsei);
>>
>>
>> --
>> Lawrence Crowl
>
Richard Biener Oct. 4, 2012, 8 a.m. UTC | #3
On Wed, Oct 3, 2012 at 6:52 PM, Lawrence Crowl <crowl@googlers.com> wrote:
> On 10/3/12, Martin Jambor <mjambor@suse.cz> wrote:
>> On Tue, Oct 02, 2012 at 05:32:38PM -0700, Lawrence Crowl wrote:
>>> Updated Patch
>>>
>>> Add functions symtab_node_def::try_function and
>>> symtab_node_def::try_variable.
>>
>> Even though I hate to be bikeshedding, I must say I really dislike the
>> names, especially try_function.  Not only I believe it should be
>> consistent with the name of the type it returns but, more importantly,
>> it looks as if it had something to do with struct function which is an
>> entirely different thing.
>>
>> I understand the names cgraph_node and varpool_node are slightly
>> anachronistic in the symtab world, but still I think that they are
>> perfectly usable, do not present a real obstacle to newcomers
>> (cgraph_nodes do form the call graph, after all) and we are all used
>> to them.  Therefore I'd be in favor of keeping them and changing the
>> try_stuff function names accordingly.
>
> These names were requested by Jan Hubicka to conform with
> his planned type renaming.  So, your concern will be addressed
> over time.

We can rename the try_* functions at the same time we rename
cgraph_node/varpool_node.  It's bad to be inconsistent at any time,
especially if you introduce a _new_ concept.

Richard.

>>> These function return a pointer to the more specific type (e.g.
>>> cgraph_node*)
>>> if and only if the general type (symtab_node aka symtab_node_def*) is an
>>> instance of the specific type.  These functions are essentially checked
>>> down
>>> casts.
>>>
>>> These functions reduce compile time and increase type safety when treating
>>> a
>>> generic item as a more specific item.  In essence, the code change is
>>> from
>>>
>>>   if (symtab_function_p (node))
>>>     {
>>>       struct cgraph_node *cnode = cgraph (node);
>>>       ....
>>>     }
>>>
>>> to
>>>
>>>   if (cgraph_node *cnode = node->try_function ())
>>>     {
>>>       ....
>>>     }
>>>
>>> The necessary conditional test defines a variable that holds a known good
>>> pointer to the specific item and avoids subsequent conversion calls and
>>> the assertion checks that may come with them.
>>>
>>> When, the property test is embedded within a larger condition, the
>>> variable
>>> declaration gets pulled out of the condition.  (This leaves some room for
>>> using the variable inappropriately.)
>>>
>>>   if (symtab_variable_p (node)
>>>       && varpool (node)->finalized)
>>>     varpool_analyze_node (varpool (node));
>>>
>>> becomes
>>>
>>>   varpool_node *vnode = node->try_variable ();
>>>   if (vnode && vnode->finalized)
>>>     varpool_analyze_node (vnode);
>>>
>>> Note that we have converted two sets of assertions in the calls to
>>> varpool
>>> into safe and efficient use of a variable.
>>>
>>>
>>> There are remaining calls to symtab_function_p and symtab_variable_p that
>>> do not involve a pointer to a more specific type.  These have been
>>> converted
>>> to calls to a member functions symtab_node_def::is_function and
>>> symtab_node_def::is_variable.  The original predicate functions have been
>>> removed.
>>>
>>>
>>> The cgraph.h header defined both a struct and a function with the name
>>> varpool_node.  This name overloading can cause some unintuitive error
>>> messages
>>> when, as is common in C++, one omits the struct keyword when using the
>>> type.
>>> I have renamed the function to varpool_node_for_decl.
>>>
>>>
>>> The new code bootstraps .616% faster with a 99% confidence of being
>>> faster.
>>>
>>>
>>> Tested on x86_64.
>>>
>>>
>>> Okay for trunk?
>>>
>>>
>>> Index: gcc/ChangeLog
>>>
>>> 2012-10-02  Lawrence Crowl  <crowl@google.com
>>>
>>>      * cgraph.h (varpool_node): Rename to varpool_node_for_decl.
>>>      Adjust callers to match.
>>>      (symtab_node_def::try_function): New.
>>>      Change most calls to symtab_function_p with calls to
>>>      symtab_node_def::try_function.
>>>      (symtab_node_def::try_variable): New.
>>>      Change most calls to symtab_variable_p with calls to
>>>      symtab_node_def::try_variable.
>>>      (symtab_function_p): Rename to symtab_node_def::is_function.
>>>      Adjust remaining callers to match.
>>>      (symtab_variable_p): Rename to symtab_node_def::is_variable.
>>>      Adjust remaining callers to match.
>>>      * cgraph.c (cgraph_node_for_asm): Remove redundant call to
>>>      symtab_node_for_asm.
>>>      * cgraphunit.c (symbol_finalized_and_needed): New.
>>>      (symbol_finalized): New.
>>>      (cgraph_analyze_functions): Split complicated conditionals out into
>>>      above new functions.
>>>
>>>
>>> Index: gcc/lto-symtab.c
>>> ===================================================================
>>> --- gcc/lto-symtab.c (revision 192010)
>>> +++ gcc/lto-symtab.c (working copy)
>>> @@ -566,11 +566,11 @@ lto_symtab_merge_cgraph_nodes_1 (symtab_
>>>
>>>        if (!symtab_real_symbol_p (e))
>>>      continue;
>>> -      if (symtab_function_p (e)
>>> -      && !DECL_BUILT_IN (e->symbol.decl))
>>> -    lto_cgraph_replace_node (cgraph (e), cgraph (prevailing));
>>> -      if (symtab_variable_p (e))
>>> -    lto_varpool_replace_node (varpool (e), varpool (prevailing));
>>> +      cgraph_node *ce = e->try_function ();
>>> +      if (ce && !DECL_BUILT_IN (e->symbol.decl))
>>> +    lto_cgraph_replace_node (ce, cgraph (prevailing));
>>> +      if (varpool_node *ve = e->try_variable ())
>>> +    lto_varpool_replace_node (ve, varpool (prevailing));
>>>      }
>>>
>>>    return;
>>> Index: gcc/cgraphbuild.c
>>> ===================================================================
>>> --- gcc/cgraphbuild.c        (revision 192010)
>>> +++ gcc/cgraphbuild.c        (working copy)
>>> @@ -84,7 +84,7 @@ record_reference (tree *tp, int *walk_su
>>>
>>>        if (TREE_CODE (decl) == VAR_DECL)
>>>      {
>>> -      struct varpool_node *vnode = varpool_node (decl);
>>> +      struct varpool_node *vnode = varpool_node_for_decl (decl);
>>>        ipa_record_reference ((symtab_node)ctx->varpool_node,
>>>                              (symtab_node)vnode,
>>>                              IPA_REF_ADDR, NULL);
>>> @@ -123,7 +123,7 @@ record_type_list (struct cgraph_node *no
>>>        type = TREE_OPERAND (type, 0);
>>>        if (TREE_CODE (type) == VAR_DECL)
>>>          {
>>> -          struct varpool_node *vnode = varpool_node (type);
>>> +          struct varpool_node *vnode = varpool_node_for_decl (type);
>>>            ipa_record_reference ((symtab_node)node,
>>>                                  (symtab_node)vnode,
>>>                                  IPA_REF_ADDR, NULL);
>>> @@ -233,7 +233,7 @@ mark_address (gimple stmt, tree addr, vo
>>>    else if (addr && TREE_CODE (addr) == VAR_DECL
>>>         && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
>>>      {
>>> -      struct varpool_node *vnode = varpool_node (addr);
>>> +      struct varpool_node *vnode = varpool_node_for_decl (addr);
>>>
>>>        ipa_record_reference ((symtab_node)data,
>>>                          (symtab_node)vnode,
>>> @@ -262,7 +262,7 @@ mark_load (gimple stmt, tree t, void *da
>>>    else if (t && TREE_CODE (t) == VAR_DECL
>>>         && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
>>>      {
>>> -      struct varpool_node *vnode = varpool_node (t);
>>> +      struct varpool_node *vnode = varpool_node_for_decl (t);
>>>
>>>        ipa_record_reference ((symtab_node)data,
>>>                          (symtab_node)vnode,
>>> @@ -280,7 +280,7 @@ mark_store (gimple stmt, tree t, void *d
>>>    if (t && TREE_CODE (t) == VAR_DECL
>>>        && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
>>>      {
>>> -      struct varpool_node *vnode = varpool_node (t);
>>> +      struct varpool_node *vnode = varpool_node_for_decl (t);
>>>
>>>        ipa_record_reference ((symtab_node)data,
>>>                          (symtab_node)vnode,
>>> @@ -392,7 +392,7 @@ void
>>>  record_references_in_initializer (tree decl, bool only_vars)
>>>  {
>>>    struct pointer_set_t *visited_nodes = pointer_set_create ();
>>> -  struct varpool_node *node = varpool_node (decl);
>>> +  struct varpool_node *node = varpool_node_for_decl (decl);
>>>    struct record_reference_ctx ctx = {false, NULL};
>>>
>>>    ctx.varpool_node = node;
>>> Index: gcc/cgraph.c
>>> ===================================================================
>>> --- gcc/cgraph.c     (revision 192010)
>>> +++ gcc/cgraph.c     (working copy)
>>> @@ -503,12 +503,15 @@ cgraph_add_thunk (struct cgraph_node *de
>>>  struct cgraph_node *
>>>  cgraph_node_for_asm (tree asmname)
>>>  {
>>> -  symtab_node node = symtab_node_for_asm (asmname);
>>> -
>>>    /* We do not want to look at inline clones.  */
>>> -  for (node = symtab_node_for_asm (asmname); node; node =
>>> node->symbol.next_sharing_asm_name)
>>> -    if (symtab_function_p (node) && !cgraph(node)->global.inlined_to)
>>> -      return cgraph (node);
>>> +  for (symtab_node node = symtab_node_for_asm (asmname);
>>> +       node;
>>> +       node = node->symbol.next_sharing_asm_name)
>>> +    {
>>> +      cgraph_node *cn = node->try_function ();
>>> +      if (cn && !cn->global.inlined_to)
>>> +    return cn;
>>> +    }
>>>    return NULL;
>>>  }
>>>
>>> Index: gcc/cgraph.h
>>> ===================================================================
>>> --- gcc/cgraph.h     (revision 192010)
>>> +++ gcc/cgraph.h     (working copy)
>>> @@ -456,13 +456,56 @@ struct GTY(()) asm_node {
>>>  /* Symbol table entry.  */
>>>  union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"),
>>>         chain_prev ("%h.symbol.previous"))) symtab_node_def {
>>> +  /* Dynamic type testers. */
>>> +  bool GTY((skip)) is_function ();
>>> +  bool GTY((skip)) is_variable ();
>>> +  /* Conditional accessors return null if not the requested type.  */
>>> +  cgraph_node * GTY((skip)) try_function ();
>>> +  varpool_node * GTY((skip)) try_variable ();
>>> +
>>>    struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol;
>>> -  /* Use cgraph (symbol) accessor to get cgraph_node.  */
>>> +  /* To access the following fields,
>>> +     use the conditional accessors try_function and try_variable above
>>> +     or the asserting accessor functions cgraph and varpool.  */
>>>    struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function;
>>> -  /* Use varpool (symbol) accessor to get varpool_node.  */
>>>    struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable;
>>>  };
>>>
>>> +/* Report whether or not THIS symtab node is a function, aka cgraph_node.
>>>  */
>>> +
>>> +inline bool
>>> +symtab_node_def::is_function ()
>>> +{
>>> +  return symbol.type == SYMTAB_FUNCTION;
>>> +}
>>> +
>>> +/* Report whether or not THIS symtab node is a vriable, aka varpool_node.
>>>  */
>>> +
>>> +inline bool
>>> +symtab_node_def::is_variable ()
>>> +{
>>> +  return symbol.type == SYMTAB_VARIABLE;
>>> +}
>>> +
>>> +/* If THIS symtab node is a function, return a pointer to the
>>> cgraph_node,
>>> +   otherwise return NULL.  */
>>> +
>>> +inline cgraph_node *
>>> +symtab_node_def::try_function ()
>>> +{
>>> +  return is_function () ? &x_function : NULL;
>>> +}
>>> +
>>> +/* If THIS symtab node is a variable, return a pointer to the
>>> varpool_node,
>>> +   otherwise return NULL.  */
>>> +
>>> +inline varpool_node *
>>> +symtab_node_def::try_variable()
>>> +{
>>> +  return is_variable () ? &x_variable : NULL;
>>> +}
>>> +
>>> +
>>>  extern GTY(()) symtab_node symtab_nodes;
>>>  extern GTY(()) int cgraph_n_nodes;
>>>  extern GTY(()) int cgraph_max_uid;
>>> @@ -685,7 +728,7 @@ bool cgraph_maybe_hot_edge_p (struct cgr
>>>  bool cgraph_optimize_for_size_p (struct cgraph_node *);
>>>
>>>  /* In varpool.c  */
>>> -struct varpool_node *varpool_node (tree);
>>> +struct varpool_node *varpool_node_for_decl (tree);
>>>  struct varpool_node *varpool_node_for_asm (tree asmname);
>>>  void varpool_mark_needed_node (struct varpool_node *);
>>>  void debug_varpool (void);
>>> @@ -715,19 +758,6 @@ void varpool_add_new_variable (tree);
>>>  void symtab_initialize_asm_name_hash (void);
>>>  void symtab_prevail_in_asm_name_hash (symtab_node node);
>>>
>>> -/* Return true when NODE is function.  */
>>> -static inline bool
>>> -symtab_function_p (symtab_node node)
>>> -{
>>> -  return node->symbol.type == SYMTAB_FUNCTION;
>>> -}
>>> -
>>> -/* Return true when NODE is variable.  */
>>> -static inline bool
>>> -symtab_variable_p (symtab_node node)
>>> -{
>>> -  return node->symbol.type == SYMTAB_VARIABLE;
>>> -}
>>>
>>>  /* Return callgraph node for given symbol and check it is a function. */
>>>  static inline struct cgraph_node *
>>> @@ -800,10 +830,8 @@ varpool_first_variable (void)
>>>  {
>>>    symtab_node node;
>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>> -    {
>>> -      if (symtab_variable_p (node))
>>> -    return varpool (node);
>>> -    }
>>> +    if (varpool_node *vnode = node->try_variable ())
>>> +      return vnode;
>>>    return NULL;
>>>  }
>>>
>>> @@ -813,10 +841,8 @@ varpool_next_variable (struct varpool_no
>>>  {
>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>    for (; node1; node1 = node1->symbol.next)
>>> -    {
>>> -      if (symtab_variable_p (node1))
>>> -    return varpool (node1);
>>> -    }
>>> +    if (varpool_node *vnode1 = node1->try_variable ())
>>> +      return vnode1;
>>>    return NULL;
>>>  }
>>>  /* Walk all variables.  */
>>> @@ -832,9 +858,9 @@ varpool_first_static_initializer (void)
>>>    symtab_node node;
>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>      {
>>> -      if (symtab_variable_p (node)
>>> -      && DECL_INITIAL (node->symbol.decl))
>>> -    return varpool (node);
>>> +      varpool_node *vnode = node->try_variable ();
>>> +      if (vnode && DECL_INITIAL (node->symbol.decl))
>>> +    return vnode;
>>>      }
>>>    return NULL;
>>>  }
>>> @@ -846,9 +872,9 @@ varpool_next_static_initializer (struct
>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>    for (; node1; node1 = node1->symbol.next)
>>>      {
>>> -      if (symtab_variable_p (node1)
>>> -      && DECL_INITIAL (node1->symbol.decl))
>>> -    return varpool (node1);
>>> +      varpool_node *vnode1 = node1->try_variable ();
>>> +      if (vnode1 && DECL_INITIAL (node1->symbol.decl))
>>> +    return vnode1;
>>>      }
>>>    return NULL;
>>>  }
>>> @@ -865,8 +891,9 @@ varpool_first_defined_variable (void)
>>>    symtab_node node;
>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>      {
>>> -      if (symtab_variable_p (node) && varpool (node)->analyzed)
>>> -    return varpool (node);
>>> +      varpool_node *vnode = node->try_variable ();
>>> +      if (vnode && vnode->analyzed)
>>> +    return vnode;
>>>      }
>>>    return NULL;
>>>  }
>>> @@ -878,8 +905,9 @@ varpool_next_defined_variable (struct va
>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>    for (; node1; node1 = node1->symbol.next)
>>>      {
>>> -      if (symtab_variable_p (node1) && varpool (node1)->analyzed)
>>> -    return varpool (node1);
>>> +      varpool_node *vnode1 = node1->try_variable ();
>>> +      if (vnode1 && vnode1->analyzed)
>>> +    return vnode1;
>>>      }
>>>    return NULL;
>>>  }
>>> @@ -895,8 +923,9 @@ cgraph_first_defined_function (void)
>>>    symtab_node node;
>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>      {
>>> -      if (symtab_function_p (node) && cgraph (node)->analyzed)
>>> -    return cgraph (node);
>>> +      cgraph_node *cn = node->try_function ();
>>> +      if (cn && cn->analyzed)
>>> +    return cn;
>>>      }
>>>    return NULL;
>>>  }
>>> @@ -908,8 +937,9 @@ cgraph_next_defined_function (struct cgr
>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>    for (; node1; node1 = node1->symbol.next)
>>>      {
>>> -      if (symtab_function_p (node1) && cgraph (node1)->analyzed)
>>> -    return cgraph (node1);
>>> +      cgraph_node *cn1 = node1->try_function ();
>>> +      if (cn1 && cn1->analyzed)
>>> +    return cn1;
>>>      }
>>>    return NULL;
>>>  }
>>> @@ -925,10 +955,8 @@ cgraph_first_function (void)
>>>  {
>>>    symtab_node node;
>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>> -    {
>>> -      if (symtab_function_p (node))
>>> -    return cgraph (node);
>>> -    }
>>> +    if (cgraph_node *cn = node->try_function ())
>>> +      return cn;
>>>    return NULL;
>>>  }
>>>
>>> @@ -938,10 +966,8 @@ cgraph_next_function (struct cgraph_node
>>>  {
>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>    for (; node1; node1 = node1->symbol.next)
>>> -    {
>>> -      if (symtab_function_p (node1))
>>> -    return cgraph (node1);
>>> -    }
>>> +    if (cgraph_node *cn1 = node1->try_function ())
>>> +      return cn1;
>>>    return NULL;
>>>  }
>>>  /* Walk all functions.  */
>>> @@ -968,9 +994,9 @@ cgraph_first_function_with_gimple_body (
>>>    symtab_node node;
>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>      {
>>> -      if (symtab_function_p (node)
>>> -      && cgraph_function_with_gimple_body_p (cgraph (node)))
>>> -    return cgraph (node);
>>> +      cgraph_node *cn = node->try_function ();
>>> +      if (cn && cgraph_function_with_gimple_body_p (cn))
>>> +    return cn;
>>>      }
>>>    return NULL;
>>>  }
>>> @@ -982,9 +1008,9 @@ cgraph_next_function_with_gimple_body (s
>>>    symtab_node node1 = node->symbol.next;
>>>    for (; node1; node1 = node1->symbol.next)
>>>      {
>>> -      if (symtab_function_p (node1)
>>> -      && cgraph_function_with_gimple_body_p (cgraph (node1)))
>>> -    return cgraph (node1);
>>> +      cgraph_node *cn1 = node1->try_function ();
>>> +      if (cn1 && cgraph_function_with_gimple_body_p (cn1))
>>> +    return cn1;
>>>      }
>>>    return NULL;
>>>  }
>>> @@ -1183,7 +1209,7 @@ cgraph_alias_aliased_node (struct cgraph
>>>
>>>    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
>>>    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
>>> -  if (symtab_function_p (ref->referred))
>>> +  if (ref->referred->is_function ())
>>>      return ipa_ref_node (ref);
>>>    return NULL;
>>>  }
>>> @@ -1197,7 +1223,7 @@ varpool_alias_aliased_node (struct varpo
>>>
>>>    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
>>>    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
>>> -  if (symtab_variable_p (ref->referred))
>>> +  if (ref->referred->is_variable ())
>>>      return ipa_ref_varpool_node (ref);
>>>    return NULL;
>>>  }
>>> @@ -1328,7 +1354,7 @@ symtab_real_symbol_p (symtab_node node)
>>>    struct cgraph_node *cnode;
>>>    struct ipa_ref *ref;
>>>
>>> -  if (!symtab_function_p (node))
>>> +  if (!node->is_function ())
>>>      return true;
>>>    cnode = cgraph (node);
>>>    if (cnode->global.inlined_to)
>>> Index: gcc/tree-emutls.c
>>> ===================================================================
>>> --- gcc/tree-emutls.c        (revision 192010)
>>> +++ gcc/tree-emutls.c        (working copy)
>>> @@ -260,7 +260,7 @@ get_emutls_init_templ_addr (tree decl)
>>>    /* Create varpool node for the new variable and finalize it if it is
>>>       not external one.  */
>>>    if (DECL_EXTERNAL (to))
>>> -    varpool_node (to);
>>> +    varpool_node_for_decl (to);
>>>    else
>>>      varpool_add_new_variable (to);
>>>    return build_fold_addr_expr (to);
>>> @@ -332,7 +332,7 @@ new_emutls_decl (tree decl, tree alias_o
>>>    /* Create varpool node for the new variable and finalize it if it is
>>>       not external one.  */
>>>    if (DECL_EXTERNAL (to))
>>> -    varpool_node (to);
>>> +    varpool_node_for_decl (to);
>>>    else if (!alias_of)
>>>      varpool_add_new_variable (to);
>>>    else
>>> Index: gcc/ipa-reference.c
>>> ===================================================================
>>> --- gcc/ipa-reference.c      (revision 192010)
>>> +++ gcc/ipa-reference.c      (working copy)
>>> @@ -482,7 +482,7 @@ analyze_function (struct cgraph_node *fn
>>>    local = init_function_info (fn);
>>>    for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list,
>>> i, ref); i++)
>>>      {
>>> -      if (!symtab_variable_p (ref->referred))
>>> +      if (!ref->referred->is_variable ())
>>>      continue;
>>>        var = ipa_ref_varpool_node (ref)->symbol.decl;
>>>        if (!is_proper_for_analysis (var))
>>> @@ -979,8 +979,6 @@ stream_out_bitmap (struct lto_simple_out
>>>  static void
>>>  ipa_reference_write_optimization_summary (void)
>>>  {
>>> -  struct cgraph_node *node;
>>> -  symtab_node snode;
>>>    struct lto_simple_output_block *ob
>>>      = lto_create_simple_output_block (LTO_section_ipa_reference);
>>>    unsigned int count = 0;
>>> @@ -994,12 +992,10 @@ ipa_reference_write_optimization_summary
>>>    /* See what variables we are interested in.  */
>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>      {
>>> -      struct varpool_node *vnode;
>>> -      snode = lto_symtab_encoder_deref (encoder, i);
>>> -      if (!symtab_variable_p (snode))
>>> -    continue;
>>> -      vnode = varpool (snode);
>>> -      if (bitmap_bit_p (all_module_statics, DECL_UID
>>> (vnode->symbol.decl))
>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> +      varpool_node *vnode = snode->try_variable ();
>>> +      if (vnode
>>> +      && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
>>>        && referenced_from_this_partition_p (&vnode->symbol.ref_list,
>>> encoder))
>>>      {
>>>        tree decl = vnode->symbol.decl;
>>> @@ -1013,10 +1009,12 @@ ipa_reference_write_optimization_summary
>>>
>>>    if (ltrans_statics_bitcount)
>>>      for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>> -      if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder,
>>> i))
>>> -      && write_node_summary_p (cgraph (snode),
>>> -                               encoder, ltrans_statics))
>>> +      {
>>> +    symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> +    cgraph_node *cnode = snode->try_function ();
>>> +    if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
>>>        count++;
>>> +      }
>>>
>>>    streamer_write_uhwi_stream (ob->main_stream, count);
>>>    if (count)
>>> @@ -1027,17 +1025,15 @@ ipa_reference_write_optimization_summary
>>>    if (ltrans_statics_bitcount)
>>>      for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>        {
>>> -    snode = lto_symtab_encoder_deref (encoder, i);
>>> -    if (!symtab_function_p (snode))
>>> -      continue;
>>> -    node = cgraph (snode);
>>> -    if (write_node_summary_p (node, encoder, ltrans_statics))
>>> +    symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> +    cgraph_node *cnode = snode->try_function ();
>>> +    if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
>>>        {
>>>          ipa_reference_optimization_summary_t info;
>>>          int node_ref;
>>>
>>> -        info = get_reference_optimization_summary (node);
>>> -        node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
>>> +        info = get_reference_optimization_summary (cnode);
>>> +        node_ref = lto_symtab_encoder_encode (encoder, snode);
>>>          streamer_write_uhwi_stream (ob->main_stream, node_ref);
>>>
>>>          stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
>>> Index: gcc/cgraphunit.c
>>> ===================================================================
>>> --- gcc/cgraphunit.c (revision 192010)
>>> +++ gcc/cgraphunit.c (working copy)
>>> @@ -386,7 +386,8 @@ referred_to_p (symtab_node node)
>>>    if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
>>>      return true;
>>>    /* For functions check also calls.  */
>>> -  if (symtab_function_p (node) && cgraph (node)->callers)
>>> +  cgraph_node *cn = node->try_function ();
>>> +  if (cn && cn->callers)
>>>      return true;
>>>    return false;
>>>  }
>>> @@ -809,7 +810,7 @@ process_function_and_variable_attributes
>>>  void
>>>  varpool_finalize_decl (tree decl)
>>>  {
>>> -  struct varpool_node *node = varpool_node (decl);
>>> +  struct varpool_node *node = varpool_node_for_decl (decl);
>>>
>>>    gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
>>>
>>> @@ -836,6 +837,35 @@ varpool_finalize_decl (tree decl)
>>>      varpool_assemble_decl (node);
>>>  }
>>>
>>> +
>>> +/* Determine if a symbol is finalized and needed.  */
>>> +
>>> +inline static bool
>>> +symbol_finalized_and_needed (symtab_node node)
>>> +{
>>> +  if (cgraph_node *cnode = node->try_function ())
>>> +    return cnode->local.finalized
>>> +       && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl);
>>> +  if (varpool_node *vnode = node->try_variable ())
>>> +    return vnode->finalized
>>> +       && !DECL_EXTERNAL (vnode->symbol.decl)
>>> +       && decide_is_variable_needed (vnode, vnode->symbol.decl);
>>> +  return false;
>>> +}
>>> +
>>> +/* Determine if a symbol is finalized.  */
>>> +
>>> +inline static bool
>>> +symbol_finalized (symtab_node node)
>>> +{
>>> +  if (cgraph_node *cnode= node->try_function ())
>>> +    return cnode->local.finalized;
>>> +  if (varpool_node *vnode = node->try_variable ())
>>> +    return vnode->finalized;
>>> +  return false;
>>> +}
>>> +
>>> +
>>>  /* Discover all functions and variables that are trivially needed,
>>> analyze
>>>     them as well as all functions and variables referred by them  */
>>>
>>> @@ -870,13 +900,7 @@ cgraph_analyze_functions (void)
>>>         node != (symtab_node)first_analyzed
>>>         && node != (symtab_node)first_analyzed_var; node =
>>> node->symbol.next)
>>>      {
>>> -      if ((symtab_function_p (node)
>>> -           && cgraph (node)->local.finalized
>>> -           && cgraph_decide_is_function_needed (cgraph (node),
>>> node->symbol.decl))
>>> -          || (symtab_variable_p (node)
>>> -              && varpool (node)->finalized
>>> -              && !DECL_EXTERNAL (node->symbol.decl)
>>> -              && decide_is_variable_needed (varpool (node), node->symbol.decl)))
>>> +      if (symbol_finalized_and_needed (node))
>>>          {
>>>            enqueue_node (node);
>>>            if (!changed && cgraph_dump_file)
>>> @@ -903,18 +927,15 @@ cgraph_analyze_functions (void)
>>>        changed = true;
>>>        node = first;
>>>        first = (symtab_node)first->symbol.aux;
>>> -      if (symtab_function_p (node) && cgraph (node)->local.finalized)
>>> +      cgraph_node *cnode = node->try_function ();
>>> +      if (cnode && cnode->local.finalized)
>>>          {
>>>            struct cgraph_edge *edge;
>>> -          struct cgraph_node *cnode;
>>> -          tree decl;
>>> -
>>> -          cnode = cgraph (node);
>>> -          decl = cnode->symbol.decl;
>>> +          tree decl = cnode->symbol.decl;
>>>
>>> -          /* ??? It is possible to create extern inline function and later
>>> using
>>> -             weak alias attribute to kill its body. See
>>> -             gcc.c-torture/compile/20011119-1.c  */
>>> +          /* ??? It is possible to create extern inline function
>>> +          and later using weak alias attribute to kill its body.
>>> +          See gcc.c-torture/compile/20011119-1.c  */
>>>            if (!DECL_STRUCT_FUNCTION (decl)
>>>                && (!cnode->alias || !cnode->thunk.alias)
>>>                && !cnode->thunk.thunk_p)
>>> @@ -929,23 +950,25 @@ cgraph_analyze_functions (void)
>>>
>>>            for (edge = cnode->callees; edge; edge = edge->next_callee)
>>>              if (edge->callee->local.finalized)
>>> -              enqueue_node ((symtab_node)edge->callee);
>>> +               enqueue_node ((symtab_node)edge->callee);
>>>
>>> -          /* 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.  */
>>> +          /* 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.  */
>>>            if (DECL_ABSTRACT_ORIGIN (decl))
>>>              {
>>> -              struct cgraph_node *origin_node;
>>> -              origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
>>> +              struct cgraph_node *origin_node
>>> +              = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
>>>                origin_node->abstract_and_needed = true;
>>>              }
>>> -
>>>          }
>>> -      else if (symtab_variable_p (node)
>>> -               && varpool (node)->finalized)
>>> -        varpool_analyze_node (varpool (node));
>>> +      else
>>> +        {
>>> +          varpool_node *vnode = node->try_variable ();
>>> +          if (vnode && vnode->finalized)
>>> +            varpool_analyze_node (vnode);
>>> +        }
>>>
>>>        if (node->symbol.same_comdat_group)
>>>          {
>>> @@ -956,8 +979,7 @@ cgraph_analyze_functions (void)
>>>              enqueue_node (next);
>>>          }
>>>        for (i = 0; ipa_ref_list_reference_iterate
>>> (&node->symbol.ref_list, i, ref); i++)
>>> -        if ((symtab_function_p (ref->referred) && cgraph
>>> (ref->referred)->local.finalized)
>>> -            || (symtab_variable_p (ref->referred) && varpool
>>> (ref->referred)->finalized))
>>> +        if (symbol_finalized (ref->referred))
>>>            enqueue_node (ref->referred);
>>>            cgraph_process_new_functions ();
>>>      }
>>> @@ -985,10 +1007,9 @@ cgraph_analyze_functions (void)
>>>        symtab_remove_node (node);
>>>        continue;
>>>      }
>>> -      if (symtab_function_p (node))
>>> +      if (cgraph_node *cnode = node->try_function ())
>>>      {
>>>        tree decl = node->symbol.decl;
>>> -      struct cgraph_node *cnode = cgraph (node);
>>>
>>>        if (cnode->local.finalized && !gimple_has_body_p (decl)
>>>            && (!cnode->alias || !cnode->thunk.alias)
>>> @@ -1070,7 +1091,7 @@ handle_alias_pairs (void)
>>>      }
>>>
>>>        if (TREE_CODE (p->decl) == FUNCTION_DECL
>>> -          && target_node && symtab_function_p (target_node))
>>> +          && target_node && target_node->is_function ())
>>>      {
>>>        struct cgraph_node *src_node = cgraph_get_node (p->decl);
>>>        if (src_node && src_node->local.finalized)
>>> @@ -1079,7 +1100,7 @@ handle_alias_pairs (void)
>>>        VEC_unordered_remove (alias_pair, alias_pairs, i);
>>>      }
>>>        else if (TREE_CODE (p->decl) == VAR_DECL
>>> -           && target_node && symtab_variable_p (target_node))
>>> +           && target_node && target_node->is_variable ())
>>>      {
>>>        varpool_create_variable_alias (p->decl, target_node->symbol.decl);
>>>        VEC_unordered_remove (alias_pair, alias_pairs, i);
>>> Index: gcc/cp/decl2.c
>>> ===================================================================
>>> --- gcc/cp/decl2.c   (revision 192010)
>>> +++ gcc/cp/decl2.c   (working copy)
>>> @@ -1778,7 +1778,7 @@ import_export_class (tree ctype)
>>>  static bool
>>>  var_finalized_p (tree var)
>>>  {
>>> -  return varpool_node (var)->finalized;
>>> +  return varpool_node_for_decl (var)->finalized;
>>>  }
>>>
>>>  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
>>> @@ -1896,7 +1896,7 @@ maybe_emit_vtables (tree ctype)
>>>      TREE_ASM_WRITTEN (vtbl) = 1;
>>>        else if (DECL_ONE_ONLY (vtbl))
>>>      {
>>> -      current = varpool_node (vtbl);
>>> +      current = varpool_node_for_decl (vtbl);
>>>        if (last)
>>>          symtab_add_to_same_comdat_group ((symtab_node) current,
>>> (symtab_node) last);
>>>        last = current;
>>> Index: gcc/ipa-ref.c
>>> ===================================================================
>>> --- gcc/ipa-ref.c    (revision 192010)
>>> +++ gcc/ipa-ref.c    (working copy)
>>> @@ -42,7 +42,7 @@ ipa_record_reference (symtab_node referr
>>>    struct ipa_ref_list *list, *list2;
>>>    VEC(ipa_ref_t,gc) *old_references;
>>>
>>> -  gcc_checking_assert (!stmt || symtab_function_p (referring_node));
>>> +  gcc_checking_assert (!stmt || referring_node->is_function ());
>>>    gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
>>>
>>>    list = &referring_node->symbol.ref_list;
>>> Index: gcc/lto-cgraph.c
>>> ===================================================================
>>> --- gcc/lto-cgraph.c (revision 192010)
>>> +++ gcc/lto-cgraph.c (working copy)
>>> @@ -665,7 +665,7 @@ add_references (lto_symtab_encoder_t enc
>>>    int i;
>>>    struct ipa_ref *ref;
>>>    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
>>> -    if (symtab_function_p (ref->referred))
>>> +    if (ref->referred->is_function ())
>>>        add_node_to (encoder, ipa_ref_node (ref), false);
>>>      else
>>>        lto_symtab_encoder_encode (encoder, ref->referred);
>>> @@ -716,9 +716,8 @@ compute_ltrans_boundary (lto_symtab_enco
>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>      {
>>>        symtab_node node = lto_symtab_encoder_deref (encoder, i);
>>> -      if (symtab_variable_p (node))
>>> +      if (varpool_node *vnode = node->try_variable ())
>>>      {
>>> -      struct varpool_node *vnode = varpool (node);
>>>        if (DECL_INITIAL (vnode->symbol.decl)
>>>            && !lto_symtab_encoder_encode_initializer_p (encoder,
>>>                                                         vnode)
>>> @@ -782,8 +781,8 @@ output_symtab (void)
>>>    for (i = 0; i < n_nodes; i++)
>>>      {
>>>        symtab_node node = lto_symtab_encoder_deref (encoder, i);
>>> -      if (symtab_function_p (node))
>>> -        lto_output_node (ob, cgraph (node), encoder);
>>> +      if (cgraph_node *cnode = node->try_function ())
>>> +        lto_output_node (ob, cnode, encoder);
>>>        else
>>>          lto_output_varpool_node (ob, varpool (node), encoder);
>>>
>>> @@ -969,7 +968,7 @@ input_varpool_node (struct lto_file_decl
>>>    order = streamer_read_hwi (ib) + order_base;
>>>    decl_index = streamer_read_uhwi (ib);
>>>    var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
>>> -  node = varpool_node (var_decl);
>>> +  node = varpool_node_for_decl (var_decl);
>>>    node->symbol.order = order;
>>>    if (order >= symtab_order)
>>>      symtab_order = order + 1;
>>> @@ -1130,14 +1129,14 @@ input_cgraph_1 (struct lto_file_decl_dat
>>>    /* AUX pointers should be all non-zero for function nodes read from
>>> the stream.  */
>>>  #ifdef ENABLE_CHECKING
>>>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>>> -    gcc_assert (node->symbol.aux || !symtab_function_p (node));
>>> +    gcc_assert (node->symbol.aux || !node->is_function ());
>>>  #endif
>>>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>>>      {
>>>        int ref;
>>> -      if (symtab_function_p (node))
>>> +      if (cgraph_node *cnode = node->try_function ())
>>>      {
>>> -      ref = (int) (intptr_t) cgraph (node)->global.inlined_to;
>>> +      ref = (int) (intptr_t) cnode->global.inlined_to;
>>>
>>>        /* We share declaration of builtins, so we may read same node twice.
>>> */
>>>        if (!node->symbol.aux)
>>> @@ -1146,9 +1145,9 @@ input_cgraph_1 (struct lto_file_decl_dat
>>>
>>>        /* Fixup inlined_to from reference to pointer.  */
>>>        if (ref != LCC_NOT_FOUND)
>>> -        cgraph (node)->global.inlined_to = cgraph (VEC_index
>>> (symtab_node, nodes, ref));
>>> +        cnode->global.inlined_to = cgraph (VEC_index (symtab_node, nodes,
>>> ref));
>>>        else
>>> -        cgraph (node)->global.inlined_to = NULL;
>>> +        cnode->global.inlined_to = NULL;
>>>      }
>>>
>>>        ref = (int) (intptr_t) node->symbol.same_comdat_group;
>>> @@ -1160,7 +1159,7 @@ input_cgraph_1 (struct lto_file_decl_dat
>>>      node->symbol.same_comdat_group = NULL;
>>>      }
>>>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>>> -    node->symbol.aux = symtab_function_p (node) ? (void *)1 : NULL;
>>> +    node->symbol.aux = node->is_function () ? (void *)1 : NULL;
>>>    return nodes;
>>>  }
>>>
>>> @@ -1435,7 +1434,6 @@ output_node_opt_summary (struct output_b
>>>  static void
>>>  output_cgraph_opt_summary (void)
>>>  {
>>> -  symtab_node node;
>>>    int i, n_nodes;
>>>    lto_symtab_encoder_t encoder;
>>>    struct output_block *ob = create_output_block
>>> (LTO_section_cgraph_opt_sum);
>>> @@ -1445,18 +1443,21 @@ output_cgraph_opt_summary (void)
>>>    encoder = ob->decl_state->symtab_node_encoder;
>>>    n_nodes = lto_symtab_encoder_size (encoder);
>>>    for (i = 0; i < n_nodes; i++)
>>> -    if (symtab_function_p (node = lto_symtab_encoder_deref (encoder, i))
>>> -    && output_cgraph_opt_summary_p (cgraph (node)))
>>> -      count++;
>>> +    {
>>> +      symtab_node node = lto_symtab_encoder_deref (encoder, i);
>>> +      cgraph_node *cnode = node->try_function ();
>>> +      if (cnode && output_cgraph_opt_summary_p (cnode))
>>> +    count++;
>>> +    }
>>>    streamer_write_uhwi (ob, count);
>>>    for (i = 0; i < n_nodes; i++)
>>>      {
>>> -      node = lto_symtab_encoder_deref (encoder, i);
>>> -      if (symtab_function_p (node)
>>> -      && output_cgraph_opt_summary_p (cgraph (node)))
>>> +      symtab_node node = lto_symtab_encoder_deref (encoder, i);
>>> +      cgraph_node *cnode = node->try_function ();
>>> +      if (cnode && output_cgraph_opt_summary_p (cnode))
>>>      {
>>>        streamer_write_uhwi (ob, i);
>>> -      output_node_opt_summary (ob, cgraph (node), encoder);
>>> +      output_node_opt_summary (ob, cnode, encoder);
>>>      }
>>>      }
>>>    produce_asm (ob, NULL);
>>> Index: gcc/lto-streamer-out.c
>>> ===================================================================
>>> --- gcc/lto-streamer-out.c   (revision 192010)
>>> +++ gcc/lto-streamer-out.c   (working copy)
>>> @@ -972,7 +972,6 @@ copy_function (struct cgraph_node *node)
>>>  static void
>>>  lto_output (void)
>>>  {
>>> -  struct cgraph_node *node;
>>>    struct lto_out_decl_state *decl_state;
>>>  #ifdef ENABLE_CHECKING
>>>    bitmap output = lto_bitmap_alloc ();
>>> @@ -988,10 +987,9 @@ lto_output (void)
>>>    for (i = 0; i < n_nodes; i++)
>>>      {
>>>        symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> -      if (!symtab_function_p (snode))
>>> -    continue;
>>> -      node = cgraph (snode);
>>> -      if (lto_symtab_encoder_encode_body_p (encoder, node)
>>> +      cgraph_node *node = snode->try_function ();
>>> +      if (node
>>> +      && lto_symtab_encoder_encode_body_p (encoder, node)
>>>        && !node->alias
>>>        && !node->thunk.thunk_p)
>>>      {
>>> @@ -1285,8 +1283,6 @@ produce_symtab (struct output_block *ob)
>>>    struct streamer_tree_cache_d *cache = ob->writer_cache;
>>>    char *section_name = lto_get_section_name (LTO_section_symtab, NULL,
>>> NULL);
>>>    struct pointer_set_t *seen;
>>> -  struct cgraph_node *node;
>>> -  struct varpool_node *vnode;
>>>    struct lto_output_stream stream;
>>>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>>>    int i;
>>> @@ -1302,49 +1298,52 @@ produce_symtab (struct output_block *ob)
>>>       This is done so only to handle duplicated symbols in cgraph.  */
>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>      {
>>> -      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> +      cgraph_node *cnode = snode->try_function ();
>>> +      if (!cnode)
>>>      continue;
>>> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
>>> -      if (DECL_EXTERNAL (node->symbol.decl))
>>> +      if (DECL_EXTERNAL (cnode->symbol.decl))
>>>      continue;
>>> -      if (DECL_COMDAT (node->symbol.decl)
>>> -      && cgraph_comdat_can_be_unshared_p (node))
>>> +      if (DECL_COMDAT (cnode->symbol.decl)
>>> +      && cgraph_comdat_can_be_unshared_p (cnode))
>>>      continue;
>>> -      if ((node->alias && !node->thunk.alias) ||
>>> node->global.inlined_to)
>>> +      if ((cnode->alias && !cnode->thunk.alias) ||
>>> cnode->global.inlined_to)
>>>      continue;
>>> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
>>> +      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
>>>      }
>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>      {
>>> -      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> +      cgraph_node *cnode = snode->try_function ();
>>> +      if (!cnode)
>>>      continue;
>>> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
>>> -      if (!DECL_EXTERNAL (node->symbol.decl))
>>> +      if (!DECL_EXTERNAL (cnode->symbol.decl))
>>>      continue;
>>>        /* We keep around unused extern inlines in order to be able to
>>> inline
>>>       them indirectly or via vtables.  Do not output them to symbol
>>>       table: they end up being undefined and just consume space.  */
>>> -      if (!node->symbol.address_taken && !node->callers)
>>> +      if (!cnode->symbol.address_taken && !cnode->callers)
>>>      continue;
>>> -      if (DECL_COMDAT (node->symbol.decl)
>>> -      && cgraph_comdat_can_be_unshared_p (node))
>>> +      if (DECL_COMDAT (cnode->symbol.decl)
>>> +      && cgraph_comdat_can_be_unshared_p (cnode))
>>>      continue;
>>> -      if ((node->alias && !node->thunk.alias) ||
>>> node->global.inlined_to)
>>> +      if ((cnode->alias && !cnode->thunk.alias) ||
>>> cnode->global.inlined_to)
>>>      continue;
>>> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
>>> +      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
>>>      }
>>>
>>>    /* Write all variables.  */
>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>      {
>>> -      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> +      varpool_node *vnode = snode->try_variable ();
>>> +      if (!vnode)
>>>      continue;
>>> -      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
>>>        if (DECL_EXTERNAL (vnode->symbol.decl))
>>>      continue;
>>>        /* COMDAT virtual tables can be unshared.  Do not declare them
>>> -     in the LTO symbol table to prevent linker from forcing them
>>> -     into the output. */
>>> +    in the LTO symbol table to prevent linker from forcing them
>>> +    into the output. */
>>>        if (DECL_COMDAT (vnode->symbol.decl)
>>>        && !vnode->symbol.force_output
>>>        && vnode->finalized
>>> @@ -1356,9 +1355,10 @@ produce_symtab (struct output_block *ob)
>>>      }
>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>      {
>>> -      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> +      varpool_node *vnode = snode->try_variable ();
>>> +      if (!vnode)
>>>      continue;
>>> -      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
>>>        if (!DECL_EXTERNAL (vnode->symbol.decl))
>>>      continue;
>>>        if (DECL_COMDAT (vnode->symbol.decl)
>>> Index: gcc/ada/gcc-interface/utils.c
>>> ===================================================================
>>> --- gcc/ada/gcc-interface/utils.c    (revision 192010)
>>> +++ gcc/ada/gcc-interface/utils.c    (working copy)
>>> @@ -5582,7 +5582,7 @@ gnat_write_global_declarations (void)
>>>                    void_type_node);
>>>        TREE_STATIC (dummy_global) = 1;
>>>        TREE_ASM_WRITTEN (dummy_global) = 1;
>>> -      node = varpool_node (dummy_global);
>>> +      node = varpool_node_for_decl (dummy_global);
>>>        node->symbol.force_output = 1;
>>>
>>>        while (!VEC_empty (tree, types_used_by_cur_var_decl))
>>> Index: gcc/ipa.c
>>> ===================================================================
>>> --- gcc/ipa.c        (revision 192010)
>>> +++ gcc/ipa.c        (working copy)
>>> @@ -84,7 +84,7 @@ process_references (struct ipa_ref_list
>>>    struct ipa_ref *ref;
>>>    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
>>>      {
>>> -      if (symtab_function_p (ref->referred))
>>> +      if (ref->referred->is_function ())
>>>      {
>>>        struct cgraph_node *node = ipa_ref_node (ref);
>>>
>>> @@ -290,10 +290,8 @@ symtab_remove_unreachable_nodes (bool be
>>>                            before_inlining_p, reachable);
>>>      }
>>>
>>> -      if (symtab_function_p (node))
>>> +      if (cgraph_node *cnode = node->try_function ())
>>>      {
>>> -      struct cgraph_node *cnode = cgraph (node);
>>> -
>>>        /* Mark the callees reachable unless they are direct calls to extern
>>>           inline functions we decided to not inline.  */
>>>        if (!in_boundary_p)
>>> @@ -332,18 +330,18 @@ symtab_remove_unreachable_nodes (bool be
>>>          }
>>>      }
>>>        /* When we see constructor of external variable, keep referred
>>> nodes in the
>>> -     boundary.  This will also hold initializers of the external vars NODE
>>> -     reffers to.  */
>>> -      if (symtab_variable_p (node)
>>> +    boundary.  This will also hold initializers of the external vars NODE
>>> +    refers to.  */
>>> +      varpool_node *vnode = node->try_variable ();
>>> +      if (vnode
>>>        && DECL_EXTERNAL (node->symbol.decl)
>>> -      && !varpool (node)->alias
>>> +      && !vnode->alias
>>>        && in_boundary_p)
>>> -        {
>>> -      int i;
>>> +    {
>>>        struct ipa_ref *ref;
>>> -      for (i = 0; ipa_ref_list_reference_iterate
>>> (&node->symbol.ref_list, i, ref); i++)
>>> +      for (int i = 0; ipa_ref_list_reference_iterate
>>> (&node->symbol.ref_list, i, ref); i++)
>>>          enqueue_node (ref->referred, &first, reachable);
>>> -        }
>>> +    }
>>>      }
>>>
>>>    /* Remove unreachable functions.   */
>>> @@ -526,7 +524,7 @@ cgraph_address_taken_from_non_vtable_p (
>>>      if (ref->use == IPA_REF_ADDR)
>>>        {
>>>      struct varpool_node *node;
>>> -    if (symtab_function_p (ref->referring))
>>> +    if (ref->referring->is_function ())
>>>        return true;
>>>      node = ipa_ref_referring_varpool_node (ref);
>>>      if (!DECL_VIRTUAL_P (node->symbol.decl))
>>> Index: gcc/ipa-inline-analysis.c
>>> ===================================================================
>>> --- gcc/ipa-inline-analysis.c        (revision 192010)
>>> +++ gcc/ipa-inline-analysis.c        (working copy)
>>> @@ -3811,22 +3811,25 @@ void
>>>  inline_write_summary (void)
>>>  {
>>>    struct cgraph_node *node;
>>> -  symtab_node snode;
>>>    struct output_block *ob = create_output_block
>>> (LTO_section_inline_summary);
>>>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>>>    unsigned int count = 0;
>>>    int i;
>>>
>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>> -    if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder,
>>> i))
>>> -    && cgraph (snode)->analyzed)
>>> -      count++;
>>> +    {
>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> +      cgraph_node *cnode = snode->try_function ();
>>> +      if (cnode && cnode->analyzed)
>>> +    count++;
>>> +    }
>>>    streamer_write_uhwi (ob, count);
>>>
>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>      {
>>> -      if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder,
>>> i))
>>> -      && (node = cgraph (snode))->analyzed)
>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>> +      cgraph_node *cnode = snode->try_function ();
>>> +      if (cnode && (node = cnode)->analyzed)
>>>      {
>>>        struct inline_summary *info = inline_summary (node);
>>>        struct bitpack_d bp;
>>> @@ -3834,7 +3837,7 @@ inline_write_summary (void)
>>>        int i;
>>>        size_time_entry *e;
>>>        struct condition *c;
>>> -
>>> +
>>>        streamer_write_uhwi (ob, lto_symtab_encoder_encode (encoder,
>>> (symtab_node)node));
>>>        streamer_write_hwi (ob, info->estimated_self_stack_size);
>>>        streamer_write_hwi (ob, info->self_size);
>>> @@ -3853,7 +3856,7 @@ inline_write_summary (void)
>>>            bp_pack_value (&bp, c->by_ref, 1);
>>>            streamer_write_bitpack (&bp);
>>>            if (c->agg_contents)
>>> -            streamer_write_uhwi (ob, c->offset);
>>> +            streamer_write_uhwi (ob, c->offset);
>>>          }
>>>        streamer_write_uhwi (ob, VEC_length (size_time_entry, info->entry));
>>>        for (i = 0;
>>> Index: gcc/lto/lto.c
>>> ===================================================================
>>> --- gcc/lto/lto.c    (revision 192010)
>>> +++ gcc/lto/lto.c    (working copy)
>>> @@ -2620,12 +2620,17 @@ lto_wpa_write_files (void)
>>>            if (!lto_symtab_encoder_in_partition_p (part->encoder, node))
>>>              {
>>>                fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name
>>> (node));
>>> -              if (symtab_function_p (node)
>>> -                  && lto_symtab_encoder_encode_body_p (part->encoder, cgraph
>>> (node)))
>>> +              cgraph_node *cnode = node->try_function ();
>>> +              if (cnode
>>> +                  && lto_symtab_encoder_encode_body_p (part->encoder, cnode))
>>>                  fprintf (cgraph_dump_file, "(body included)");
>>> -              else if (symtab_variable_p (node)
>>> -                       && lto_symtab_encoder_encode_initializer_p
>>> (part->encoder, varpool (node)))
>>> -                fprintf (cgraph_dump_file, "(initializer included)");
>>> +              else
>>> +                {
>>> +                  varpool_node *vnode = node->try_variable ();
>>> +                  if (vnode
>>> +                      && lto_symtab_encoder_encode_initializer_p (part->encoder, vnode))
>>> +                    fprintf (cgraph_dump_file, "(initializer included)");
>>> +                }
>>>              }
>>>          }
>>>        fprintf (cgraph_dump_file, "\n");
>>> Index: gcc/lto/lto-partition.c
>>> ===================================================================
>>> --- gcc/lto/lto-partition.c  (revision 192010)
>>> +++ gcc/lto/lto-partition.c  (working copy)
>>> @@ -55,22 +55,22 @@ get_symbol_class (symtab_node node)
>>>  {
>>>    /* Inline clones are always duplicated.
>>>       This include external delcarations.   */
>>> -  if (symtab_function_p (node)
>>> -      && cgraph (node)->global.inlined_to)
>>> +  cgraph_node *cnode = node->try_function ();
>>> +  if (cnode && cnode->global.inlined_to)
>>>      return SYMBOL_DUPLICATE;
>>>
>>>    /* External declarations are external.  */
>>>    if (DECL_EXTERNAL (node->symbol.decl))
>>>      return SYMBOL_EXTERNAL;
>>>
>>> -  if (symtab_variable_p (node))
>>> +  if (varpool_node *vnode = node->try_variable ())
>>>      {
>>>        /* Constant pool references use local symbol names that can not
>>>           be promoted global.  We should never put into a constant pool
>>>           objects that can not be duplicated across partitions.  */
>>>        if (DECL_IN_CONSTANT_POOL (node->symbol.decl))
>>>      return SYMBOL_DUPLICATE;
>>> -      gcc_checking_assert (varpool (node)->analyzed);
>>> +      gcc_checking_assert (vnode->analyzed);
>>>      }
>>>    /* Functions that are cloned may stay in callgraph even if they are
>>> unused.
>>>       Handle them as external; compute_ltrans_boundary take care to make
>>> @@ -145,7 +145,7 @@ add_references_to_partition (ltrans_part
>>>      /* References to a readonly variable may be constant foled into its
>>> value.
>>>         Recursively look into the initializers of the constant variable
>>> and add
>>>         references, too.  */
>>> -    else if (symtab_variable_p (ref->referred)
>>> +    else if (ref->referred->is_variable ()
>>>           && const_value_known_p (ref->referred->symbol.decl)
>>>           && !lto_symtab_encoder_in_partition_p (part->encoder,
>>> ref->referred))
>>>        {
>>> @@ -196,9 +196,8 @@ add_symbol_to_partition_1 (ltrans_partit
>>>      }
>>>    node->symbol.aux = (void *)((size_t)node->symbol.aux + 1);
>>>
>>> -  if (symtab_function_p (node))
>>> +  if (cgraph_node *cnode = node->try_function ())
>>>      {
>>> -      struct cgraph_node *cnode = cgraph (node);
>>>        struct cgraph_edge *e;
>>>        part->insns += inline_summary (cnode)->self_size;
>>>
>>> @@ -247,15 +246,15 @@ contained_in_symbol (symtab_node node)
>>>    if (lookup_attribute ("weakref",
>>>                      DECL_ATTRIBUTES (node->symbol.decl)))
>>>      return node;
>>> -  if (symtab_function_p (node))
>>> +  if (cgraph_node *cnode = node->try_function ())
>>>      {
>>> -      struct cgraph_node *cnode = cgraph_function_node (cgraph (node),
>>> NULL);
>>> +      cnode = cgraph_function_node (cnode, NULL);
>>>        if (cnode->global.inlined_to)
>>>      cnode = cnode->global.inlined_to;
>>>        return (symtab_node) cnode;
>>>      }
>>> -  else if (symtab_variable_p (node))
>>> -    return (symtab_node) varpool_variable_node (varpool (node), NULL);
>>> +  else if (varpool_node *vnode = node->try_variable ())
>>> +    return (symtab_node) varpool_variable_node (vnode, NULL);
>>>    return node;
>>>  }
>>>
>>> @@ -302,8 +301,8 @@ undo_partition (ltrans_partition partiti
>>>      pointer_set_destroy (partition->initializers_visited);
>>>        partition->initializers_visited = NULL;
>>>
>>> -      if (symtab_function_p (node))
>>> -        partition->insns -= inline_summary (cgraph (node))->self_size;
>>> +      if (cgraph_node *cnode = node->try_function ())
>>> +        partition->insns -= inline_summary (cnode)->self_size;
>>>        lto_symtab_encoder_delete_node (partition->encoder, node);
>>>        node->symbol.aux = (void *)((size_t)node->symbol.aux - 1);
>>>      }
>>> @@ -555,11 +554,10 @@ lto_balanced_map (void)
>>>        symtab_node snode = lto_symtab_encoder_deref (partition->encoder,
>>>                                                      last_visited_node);
>>>
>>> -      if (symtab_function_p (snode))
>>> +      if (cgraph_node *node = snode->try_function ())
>>>          {
>>>            struct cgraph_edge *edge;
>>>
>>> -          node = cgraph (snode);
>>>            refs = &node->symbol.ref_list;
>>>
>>>            last_visited_node++;
>>> @@ -611,7 +609,7 @@ lto_balanced_map (void)
>>>        /* Compute boundary cost of IPA REF edges and at the same time look
>>> into
>>>           variables referenced from current partition and try to add them.
>>> */
>>>        for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++)
>>> -        if (symtab_variable_p (ref->referred))
>>> +        if (ref->referred->is_variable ())
>>>            {
>>>              int index;
>>>
>>> @@ -645,7 +643,7 @@ lto_balanced_map (void)
>>>                cost++;
>>>            }
>>>        for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++)
>>> -        if (symtab_variable_p (ref->referring))
>>> +        if (ref->referring->is_variable ())
>>>            {
>>>              int index;
>>>
>>> Index: gcc/varasm.c
>>> ===================================================================
>>> --- gcc/varasm.c     (revision 192010)
>>> +++ gcc/varasm.c     (working copy)
>>> @@ -2221,7 +2221,7 @@ mark_decl_referenced (tree decl)
>>>      }
>>>    else if (TREE_CODE (decl) == VAR_DECL)
>>>      {
>>> -      struct varpool_node *node = varpool_node (decl);
>>> +      struct varpool_node *node = varpool_node_for_decl (decl);
>>>        /* C++ frontend use mark_decl_references to force COMDAT variables
>>>           to be output that might appear dead otherwise.  */
>>>        node->symbol.force_output = true;
>>> @@ -5549,7 +5549,7 @@ assemble_alias (tree decl, tree target)
>>>    if (TREE_CODE (decl) == FUNCTION_DECL)
>>>      cgraph_get_create_node (decl)->alias = true;
>>>    else
>>> -    varpool_node (decl)->alias = true;
>>> +    varpool_node_for_decl (decl)->alias = true;
>>>
>>>    /* If the target has already been emitted, we don't have to queue the
>>>       alias.  This saves a tad of memory.  */
>>> Index: gcc/symtab.c
>>> ===================================================================
>>> --- gcc/symtab.c     (revision 192010)
>>> +++ gcc/symtab.c     (working copy)
>>> @@ -104,7 +104,7 @@ eq_assembler_name (const void *p1, const
>>>  static void
>>>  insert_to_assembler_name_hash (symtab_node node)
>>>  {
>>> -  if (symtab_variable_p (node) && DECL_HARD_REGISTER
>>> (node->symbol.decl))
>>> +  if (node->is_variable () && DECL_HARD_REGISTER (node->symbol.decl))
>>>      return;
>>>    gcc_checking_assert (!node->symbol.previous_sharing_asm_name
>>>                     && !node->symbol.next_sharing_asm_name);
>>> @@ -252,8 +252,8 @@ symtab_unregister_node (symtab_node node
>>>    if (*slot == node)
>>>      {
>>>        symtab_node replacement_node = NULL;
>>> -      if (symtab_function_p (node))
>>> -    replacement_node = (symtab_node)cgraph_find_replacement_node (cgraph
>>> (node));
>>> +      if (cgraph_node *cnode = node->try_function ())
>>> +    replacement_node = (symtab_node)cgraph_find_replacement_node (cnode);
>>>        if (!replacement_node)
>>>      htab_clear_slot (symtab_hash, slot);
>>>        else
>>> @@ -294,10 +294,10 @@ symtab_get_node (const_tree decl)
>>>  void
>>>  symtab_remove_node (symtab_node node)
>>>  {
>>> -  if (symtab_function_p (node))
>>> -    cgraph_remove_node (cgraph (node));
>>> -  else if (symtab_variable_p (node))
>>> -    varpool_remove_node (varpool (node));
>>> +  if (cgraph_node *cnode = node->try_function ())
>>> +    cgraph_remove_node (cnode);
>>> +  else if (varpool_node *vnode = node->try_variable ())
>>> +    varpool_remove_node (vnode);
>>>  }
>>>
>>>  /* Initalize asm name hash unless.  */
>>> @@ -538,10 +538,10 @@ dump_symtab_base (FILE *f, symtab_node n
>>>  void
>>>  dump_symtab_node (FILE *f, symtab_node node)
>>>  {
>>> -  if (symtab_function_p (node))
>>> -    dump_cgraph_node (f, cgraph (node));
>>> -  else if (symtab_variable_p (node))
>>> -    dump_varpool_node (f, varpool (node));
>>> +  if (cgraph_node *cnode = node->try_function ())
>>> +    dump_cgraph_node (f, cnode);
>>> +  else if (varpool_node *vnode = node->try_variable ())
>>> +    dump_varpool_node (f, vnode);
>>>  }
>>>
>>>  /* Dump symbol table.  */
>>> @@ -579,7 +579,7 @@ verify_symtab_base (symtab_node node)
>>>    bool error_found = false;
>>>    symtab_node hashed_node;
>>>
>>> -  if (symtab_function_p (node))
>>> +  if (node->is_function ())
>>>      {
>>>        if (TREE_CODE (node->symbol.decl) != FUNCTION_DECL)
>>>      {
>>> @@ -587,7 +587,7 @@ verify_symtab_base (symtab_node node)
>>>            error_found = true;
>>>      }
>>>      }
>>> -  else if (symtab_variable_p (node))
>>> +  else if (node->is_variable ())
>>>      {
>>>        if (TREE_CODE (node->symbol.decl) != VAR_DECL)
>>>      {
>>> @@ -622,7 +622,7 @@ verify_symtab_base (symtab_node node)
>>>        hashed_node = hashed_node->symbol.next_sharing_asm_name;
>>>      }
>>>        if (!hashed_node
>>> -          && !(symtab_variable_p (node) || DECL_HARD_REGISTER
>>> (node->symbol.decl)))
>>> +          && !(node->is_variable () || DECL_HARD_REGISTER
>>> (node->symbol.decl)))
>>>      {
>>>            error ("node not found in symtab assembler name hash");
>>>            error_found = true;
>>> @@ -676,8 +676,8 @@ verify_symtab_node (symtab_node node)
>>>      return;
>>>
>>>    timevar_push (TV_CGRAPH_VERIFY);
>>> -  if (symtab_function_p (node))
>>> -    verify_cgraph_node (cgraph (node));
>>> +  if (cgraph_node *cnode = node->try_function ())
>>> +    verify_cgraph_node (cnode);
>>>    else
>>>      if (verify_symtab_base (node))
>>>        {
>>> Index: gcc/passes.c
>>> ===================================================================
>>> --- gcc/passes.c     (revision 192010)
>>> +++ gcc/passes.c     (working copy)
>>> @@ -201,7 +201,7 @@ rest_of_decl_compilation (tree decl,
>>>      ;
>>>    else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)
>>>         && TREE_STATIC (decl))
>>> -    varpool_node (decl);
>>> +    varpool_node_for_decl (decl);
>>>  }
>>>
>>>  /* Called after finishing a record, union or enumeral type.  */
>>> Index: gcc/varpool.c
>>> ===================================================================
>>> --- gcc/varpool.c    (revision 192010)
>>> +++ gcc/varpool.c    (working copy)
>>> @@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.
>>>
>>>  /* Return varpool node assigned to DECL.  Create new one when needed.
>>> */
>>>  struct varpool_node *
>>> -varpool_node (tree decl)
>>> +varpool_node_for_decl (tree decl)
>>>  {
>>>    struct varpool_node *node = varpool_get_node (decl);
>>>    gcc_assert (TREE_CODE (decl) == VAR_DECL
>>> @@ -114,9 +114,9 @@ debug_varpool (void)
>>>  struct varpool_node *
>>>  varpool_node_for_asm (tree asmname)
>>>  {
>>> -  symtab_node node = symtab_node_for_asm (asmname);
>>> -  if (node && symtab_variable_p (node))
>>> -    return varpool (node);
>>> +  if (symtab_node node = symtab_node_for_asm (asmname))
>>> +    if (varpool_node *vnode = node->try_variable ())
>>> +      return vnode;
>>>    return NULL;
>>>  }
>>>
>>> @@ -192,7 +192,7 @@ varpool_add_new_variable (tree decl)
>>>  {
>>>    struct varpool_node *node;
>>>    varpool_finalize_decl (decl);
>>> -  node = varpool_node (decl);
>>> +  node = varpool_node_for_decl (decl);
>>>    if (varpool_externally_visible_p (node, false))
>>>      node->symbol.externally_visible = true;
>>>  }
>>> @@ -232,7 +232,7 @@ varpool_analyze_node (struct varpool_nod
>>>      }
>>>    if (node->alias && node->alias_of)
>>>      {
>>> -      struct varpool_node *tgt = varpool_node (node->alias_of);
>>> +      struct varpool_node *tgt = varpool_node_for_decl (node->alias_of);
>>>        struct varpool_node *n;
>>>
>>>        for (n = tgt; n && n->alias;
>>> @@ -378,16 +378,21 @@ varpool_remove_unreferenced_decls (void)
>>>        for (next = node->symbol.same_comdat_group;
>>>             next != (symtab_node)node;
>>>             next = next->symbol.same_comdat_group)
>>> -        if (symtab_variable_p (next)
>>> -            && varpool (next)->analyzed)
>>> -          enqueue_node (varpool (next), &first);
>>> +        {
>>> +          varpool_node *vnext = next->try_variable ();
>>> +          if (vnext && vnext->analyzed)
>>> +            enqueue_node (vnext, &first);
>>> +        }
>>>      }
>>>        for (i = 0; ipa_ref_list_reference_iterate
>>> (&node->symbol.ref_list, i, ref); i++)
>>> -    if (symtab_variable_p (ref->referred)
>>> -        && (!DECL_EXTERNAL (ref->referred->symbol.decl)
>>> -            || varpool (ref->referred)->alias)
>>> -        && varpool (ref->referred)->analyzed)
>>> -      enqueue_node (varpool (ref->referred), &first);
>>> +    {
>>> +      varpool_node *vnode = ref->referred->try_variable ();
>>> +      if (vnode
>>> +          && (!DECL_EXTERNAL (ref->referred->symbol.decl)
>>> +              || vnode->alias)
>>> +          && vnode->analyzed)
>>> +        enqueue_node (vnode, &first);
>>> +    }
>>>      }
>>>    if (cgraph_dump_file)
>>>      fprintf (cgraph_dump_file, "\nRemoving variables:");
>>> @@ -461,7 +466,7 @@ add_new_static_var (tree type)
>>>    DECL_CONTEXT (new_decl) = NULL_TREE;
>>>    DECL_ABSTRACT (new_decl) = 0;
>>>    lang_hooks.dup_lang_specific_decl (new_decl);
>>> -  new_node = varpool_node (new_decl);
>>> +  new_node = varpool_node_for_decl (new_decl);
>>>    varpool_finalize_decl (new_decl);
>>>
>>>    return new_node->symbol.decl;
>>> @@ -477,7 +482,7 @@ varpool_create_variable_alias (tree alia
>>>
>>>    gcc_assert (TREE_CODE (decl) == VAR_DECL);
>>>    gcc_assert (TREE_CODE (alias) == VAR_DECL);
>>> -  alias_node = varpool_node (alias);
>>> +  alias_node = varpool_node_for_decl (alias);
>>>    alias_node->alias = 1;
>>>    alias_node->finalized = 1;
>>>    alias_node->alias_of = decl;
>>> Index: gcc/lto-streamer.h
>>> ===================================================================
>>> --- gcc/lto-streamer.h       (revision 192010)
>>> +++ gcc/lto-streamer.h       (working copy)
>>> @@ -1120,7 +1120,7 @@ lsei_next_function_in_partition (lto_sym
>>>  {
>>>    lsei_next (lsei);
>>>    while (!lsei_end_p (*lsei)
>>> -     && (!symtab_function_p (lsei_node (*lsei))
>>> +     && (!lsei_node (*lsei)->is_function ()
>>>           || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
>>> (*lsei))))
>>>      lsei_next (lsei);
>>>  }
>>> @@ -1133,7 +1133,7 @@ lsei_start_function_in_partition (lto_sy
>>>
>>>    if (lsei_end_p (lsei))
>>>      return lsei;
>>> -  if (!symtab_function_p (lsei_node (lsei))
>>> +  if (!(lsei_node (lsei)->is_function ())
>>>        || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
>>>      lsei_next_function_in_partition (&lsei);
>>>
>>> @@ -1146,7 +1146,7 @@ lsei_next_variable_in_partition (lto_sym
>>>  {
>>>    lsei_next (lsei);
>>>    while (!lsei_end_p (*lsei)
>>> -     && (!symtab_variable_p (lsei_node (*lsei))
>>> +     && (!lsei_node (*lsei)->is_variable ()
>>>           || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
>>> (*lsei))))
>>>      lsei_next (lsei);
>>>  }
>>> @@ -1159,7 +1159,7 @@ lsei_start_variable_in_partition (lto_sy
>>>
>>>    if (lsei_end_p (lsei))
>>>      return lsei;
>>> -  if (!symtab_variable_p (lsei_node (lsei))
>>> +  if (!lsei_node (lsei)->is_variable ()
>>>        || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
>>>      lsei_next_variable_in_partition (&lsei);
>>>
>>>
>>> --
>>> Lawrence Crowl
>>
>
>
> --
> Lawrence Crowl
Lawrence Crowl Oct. 4, 2012, 6:14 p.m. UTC | #4
On 10/4/12, Richard Guenther <richard.guenther@gmail.com> wrote:
> On Wed, Oct 3, 2012 at 6:52 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>> On 10/3/12, Martin Jambor <mjambor@suse.cz> wrote:
>>> On Tue, Oct 02, 2012 at 05:32:38PM -0700, Lawrence Crowl wrote:
>>>> Updated Patch
>>>>
>>>> Add functions symtab_node_def::try_function and
>>>> symtab_node_def::try_variable.
>>>
>>> Even though I hate to be bikeshedding, I must say I really dislike the
>>> names, especially try_function.  Not only I believe it should be
>>> consistent with the name of the type it returns but, more importantly,
>>> it looks as if it had something to do with struct function which is an
>>> entirely different thing.
>>>
>>> I understand the names cgraph_node and varpool_node are slightly
>>> anachronistic in the symtab world, but still I think that they are
>>> perfectly usable, do not present a real obstacle to newcomers
>>> (cgraph_nodes do form the call graph, after all) and we are all used
>>> to them.  Therefore I'd be in favor of keeping them and changing the
>>> try_stuff function names accordingly.
>>
>> These names were requested by Jan Hubicka to conform with
>> his planned type renaming.  So, your concern will be addressed
>> over time.
>
> We can rename the try_* functions at the same time we rename
> cgraph_node/varpool_node.  It's bad to be inconsistent at any time,
> especially if you introduce a _new_ concept.

So, Jan Hubicka requested and approved the current spelling.
What now?

>
> Richard.
>
>>>> These function return a pointer to the more specific type (e.g.
>>>> cgraph_node*)
>>>> if and only if the general type (symtab_node aka symtab_node_def*) is
>>>> an
>>>> instance of the specific type.  These functions are essentially checked
>>>> down
>>>> casts.
>>>>
>>>> These functions reduce compile time and increase type safety when
>>>> treating
>>>> a
>>>> generic item as a more specific item.  In essence, the code change is
>>>> from
>>>>
>>>>   if (symtab_function_p (node))
>>>>     {
>>>>       struct cgraph_node *cnode = cgraph (node);
>>>>       ....
>>>>     }
>>>>
>>>> to
>>>>
>>>>   if (cgraph_node *cnode = node->try_function ())
>>>>     {
>>>>       ....
>>>>     }
>>>>
>>>> The necessary conditional test defines a variable that holds a known
>>>> good
>>>> pointer to the specific item and avoids subsequent conversion calls and
>>>> the assertion checks that may come with them.
>>>>
>>>> When, the property test is embedded within a larger condition, the
>>>> variable
>>>> declaration gets pulled out of the condition.  (This leaves some room
>>>> for
>>>> using the variable inappropriately.)
>>>>
>>>>   if (symtab_variable_p (node)
>>>>       && varpool (node)->finalized)
>>>>     varpool_analyze_node (varpool (node));
>>>>
>>>> becomes
>>>>
>>>>   varpool_node *vnode = node->try_variable ();
>>>>   if (vnode && vnode->finalized)
>>>>     varpool_analyze_node (vnode);
>>>>
>>>> Note that we have converted two sets of assertions in the calls to
>>>> varpool
>>>> into safe and efficient use of a variable.
>>>>
>>>>
>>>> There are remaining calls to symtab_function_p and symtab_variable_p
>>>> that
>>>> do not involve a pointer to a more specific type.  These have been
>>>> converted
>>>> to calls to a member functions symtab_node_def::is_function and
>>>> symtab_node_def::is_variable.  The original predicate functions have
>>>> been
>>>> removed.
>>>>
>>>>
>>>> The cgraph.h header defined both a struct and a function with the name
>>>> varpool_node.  This name overloading can cause some unintuitive error
>>>> messages
>>>> when, as is common in C++, one omits the struct keyword when using the
>>>> type.
>>>> I have renamed the function to varpool_node_for_decl.
>>>>
>>>>
>>>> The new code bootstraps .616% faster with a 99% confidence of being
>>>> faster.
>>>>
>>>>
>>>> Tested on x86_64.
>>>>
>>>>
>>>> Okay for trunk?
>>>>
>>>>
>>>> Index: gcc/ChangeLog
>>>>
>>>> 2012-10-02  Lawrence Crowl  <crowl@google.com
>>>>
>>>>      * cgraph.h (varpool_node): Rename to varpool_node_for_decl.
>>>>      Adjust callers to match.
>>>>      (symtab_node_def::try_function): New.
>>>>      Change most calls to symtab_function_p with calls to
>>>>      symtab_node_def::try_function.
>>>>      (symtab_node_def::try_variable): New.
>>>>      Change most calls to symtab_variable_p with calls to
>>>>      symtab_node_def::try_variable.
>>>>      (symtab_function_p): Rename to symtab_node_def::is_function.
>>>>      Adjust remaining callers to match.
>>>>      (symtab_variable_p): Rename to symtab_node_def::is_variable.
>>>>      Adjust remaining callers to match.
>>>>      * cgraph.c (cgraph_node_for_asm): Remove redundant call to
>>>>      symtab_node_for_asm.
>>>>      * cgraphunit.c (symbol_finalized_and_needed): New.
>>>>      (symbol_finalized): New.
>>>>      (cgraph_analyze_functions): Split complicated conditionals out
>>>> into
>>>>      above new functions.
>>>>
>>>>
>>>> Index: gcc/lto-symtab.c
>>>> ===================================================================
>>>> --- gcc/lto-symtab.c (revision 192010)
>>>> +++ gcc/lto-symtab.c (working copy)
>>>> @@ -566,11 +566,11 @@ lto_symtab_merge_cgraph_nodes_1 (symtab_
>>>>
>>>>        if (!symtab_real_symbol_p (e))
>>>>      continue;
>>>> -      if (symtab_function_p (e)
>>>> -      && !DECL_BUILT_IN (e->symbol.decl))
>>>> -    lto_cgraph_replace_node (cgraph (e), cgraph (prevailing));
>>>> -      if (symtab_variable_p (e))
>>>> -    lto_varpool_replace_node (varpool (e), varpool (prevailing));
>>>> +      cgraph_node *ce = e->try_function ();
>>>> +      if (ce && !DECL_BUILT_IN (e->symbol.decl))
>>>> +    lto_cgraph_replace_node (ce, cgraph (prevailing));
>>>> +      if (varpool_node *ve = e->try_variable ())
>>>> +    lto_varpool_replace_node (ve, varpool (prevailing));
>>>>      }
>>>>
>>>>    return;
>>>> Index: gcc/cgraphbuild.c
>>>> ===================================================================
>>>> --- gcc/cgraphbuild.c        (revision 192010)
>>>> +++ gcc/cgraphbuild.c        (working copy)
>>>> @@ -84,7 +84,7 @@ record_reference (tree *tp, int *walk_su
>>>>
>>>>        if (TREE_CODE (decl) == VAR_DECL)
>>>>      {
>>>> -      struct varpool_node *vnode = varpool_node (decl);
>>>> +      struct varpool_node *vnode = varpool_node_for_decl (decl);
>>>>        ipa_record_reference ((symtab_node)ctx->varpool_node,
>>>>                              (symtab_node)vnode,
>>>>                              IPA_REF_ADDR, NULL);
>>>> @@ -123,7 +123,7 @@ record_type_list (struct cgraph_node *no
>>>>        type = TREE_OPERAND (type, 0);
>>>>        if (TREE_CODE (type) == VAR_DECL)
>>>>          {
>>>> -          struct varpool_node *vnode = varpool_node (type);
>>>> +          struct varpool_node *vnode = varpool_node_for_decl (type);
>>>>            ipa_record_reference ((symtab_node)node,
>>>>                                  (symtab_node)vnode,
>>>>                                  IPA_REF_ADDR, NULL);
>>>> @@ -233,7 +233,7 @@ mark_address (gimple stmt, tree addr, vo
>>>>    else if (addr && TREE_CODE (addr) == VAR_DECL
>>>>         && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
>>>>      {
>>>> -      struct varpool_node *vnode = varpool_node (addr);
>>>> +      struct varpool_node *vnode = varpool_node_for_decl (addr);
>>>>
>>>>        ipa_record_reference ((symtab_node)data,
>>>>                          (symtab_node)vnode,
>>>> @@ -262,7 +262,7 @@ mark_load (gimple stmt, tree t, void *da
>>>>    else if (t && TREE_CODE (t) == VAR_DECL
>>>>         && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
>>>>      {
>>>> -      struct varpool_node *vnode = varpool_node (t);
>>>> +      struct varpool_node *vnode = varpool_node_for_decl (t);
>>>>
>>>>        ipa_record_reference ((symtab_node)data,
>>>>                          (symtab_node)vnode,
>>>> @@ -280,7 +280,7 @@ mark_store (gimple stmt, tree t, void *d
>>>>    if (t && TREE_CODE (t) == VAR_DECL
>>>>        && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
>>>>      {
>>>> -      struct varpool_node *vnode = varpool_node (t);
>>>> +      struct varpool_node *vnode = varpool_node_for_decl (t);
>>>>
>>>>        ipa_record_reference ((symtab_node)data,
>>>>                          (symtab_node)vnode,
>>>> @@ -392,7 +392,7 @@ void
>>>>  record_references_in_initializer (tree decl, bool only_vars)
>>>>  {
>>>>    struct pointer_set_t *visited_nodes = pointer_set_create ();
>>>> -  struct varpool_node *node = varpool_node (decl);
>>>> +  struct varpool_node *node = varpool_node_for_decl (decl);
>>>>    struct record_reference_ctx ctx = {false, NULL};
>>>>
>>>>    ctx.varpool_node = node;
>>>> Index: gcc/cgraph.c
>>>> ===================================================================
>>>> --- gcc/cgraph.c     (revision 192010)
>>>> +++ gcc/cgraph.c     (working copy)
>>>> @@ -503,12 +503,15 @@ cgraph_add_thunk (struct cgraph_node *de
>>>>  struct cgraph_node *
>>>>  cgraph_node_for_asm (tree asmname)
>>>>  {
>>>> -  symtab_node node = symtab_node_for_asm (asmname);
>>>> -
>>>>    /* We do not want to look at inline clones.  */
>>>> -  for (node = symtab_node_for_asm (asmname); node; node =
>>>> node->symbol.next_sharing_asm_name)
>>>> -    if (symtab_function_p (node) && !cgraph(node)->global.inlined_to)
>>>> -      return cgraph (node);
>>>> +  for (symtab_node node = symtab_node_for_asm (asmname);
>>>> +       node;
>>>> +       node = node->symbol.next_sharing_asm_name)
>>>> +    {
>>>> +      cgraph_node *cn = node->try_function ();
>>>> +      if (cn && !cn->global.inlined_to)
>>>> +    return cn;
>>>> +    }
>>>>    return NULL;
>>>>  }
>>>>
>>>> Index: gcc/cgraph.h
>>>> ===================================================================
>>>> --- gcc/cgraph.h     (revision 192010)
>>>> +++ gcc/cgraph.h     (working copy)
>>>> @@ -456,13 +456,56 @@ struct GTY(()) asm_node {
>>>>  /* Symbol table entry.  */
>>>>  union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"),
>>>>         chain_prev ("%h.symbol.previous"))) symtab_node_def {
>>>> +  /* Dynamic type testers. */
>>>> +  bool GTY((skip)) is_function ();
>>>> +  bool GTY((skip)) is_variable ();
>>>> +  /* Conditional accessors return null if not the requested type.  */
>>>> +  cgraph_node * GTY((skip)) try_function ();
>>>> +  varpool_node * GTY((skip)) try_variable ();
>>>> +
>>>>    struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol;
>>>> -  /* Use cgraph (symbol) accessor to get cgraph_node.  */
>>>> +  /* To access the following fields,
>>>> +     use the conditional accessors try_function and try_variable above
>>>> +     or the asserting accessor functions cgraph and varpool.  */
>>>>    struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function;
>>>> -  /* Use varpool (symbol) accessor to get varpool_node.  */
>>>>    struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable;
>>>>  };
>>>>
>>>> +/* Report whether or not THIS symtab node is a function, aka
>>>> cgraph_node.
>>>>  */
>>>> +
>>>> +inline bool
>>>> +symtab_node_def::is_function ()
>>>> +{
>>>> +  return symbol.type == SYMTAB_FUNCTION;
>>>> +}
>>>> +
>>>> +/* Report whether or not THIS symtab node is a vriable, aka
>>>> varpool_node.
>>>>  */
>>>> +
>>>> +inline bool
>>>> +symtab_node_def::is_variable ()
>>>> +{
>>>> +  return symbol.type == SYMTAB_VARIABLE;
>>>> +}
>>>> +
>>>> +/* If THIS symtab node is a function, return a pointer to the
>>>> cgraph_node,
>>>> +   otherwise return NULL.  */
>>>> +
>>>> +inline cgraph_node *
>>>> +symtab_node_def::try_function ()
>>>> +{
>>>> +  return is_function () ? &x_function : NULL;
>>>> +}
>>>> +
>>>> +/* If THIS symtab node is a variable, return a pointer to the
>>>> varpool_node,
>>>> +   otherwise return NULL.  */
>>>> +
>>>> +inline varpool_node *
>>>> +symtab_node_def::try_variable()
>>>> +{
>>>> +  return is_variable () ? &x_variable : NULL;
>>>> +}
>>>> +
>>>> +
>>>>  extern GTY(()) symtab_node symtab_nodes;
>>>>  extern GTY(()) int cgraph_n_nodes;
>>>>  extern GTY(()) int cgraph_max_uid;
>>>> @@ -685,7 +728,7 @@ bool cgraph_maybe_hot_edge_p (struct cgr
>>>>  bool cgraph_optimize_for_size_p (struct cgraph_node *);
>>>>
>>>>  /* In varpool.c  */
>>>> -struct varpool_node *varpool_node (tree);
>>>> +struct varpool_node *varpool_node_for_decl (tree);
>>>>  struct varpool_node *varpool_node_for_asm (tree asmname);
>>>>  void varpool_mark_needed_node (struct varpool_node *);
>>>>  void debug_varpool (void);
>>>> @@ -715,19 +758,6 @@ void varpool_add_new_variable (tree);
>>>>  void symtab_initialize_asm_name_hash (void);
>>>>  void symtab_prevail_in_asm_name_hash (symtab_node node);
>>>>
>>>> -/* Return true when NODE is function.  */
>>>> -static inline bool
>>>> -symtab_function_p (symtab_node node)
>>>> -{
>>>> -  return node->symbol.type == SYMTAB_FUNCTION;
>>>> -}
>>>> -
>>>> -/* Return true when NODE is variable.  */
>>>> -static inline bool
>>>> -symtab_variable_p (symtab_node node)
>>>> -{
>>>> -  return node->symbol.type == SYMTAB_VARIABLE;
>>>> -}
>>>>
>>>>  /* Return callgraph node for given symbol and check it is a function.
>>>> */
>>>>  static inline struct cgraph_node *
>>>> @@ -800,10 +830,8 @@ varpool_first_variable (void)
>>>>  {
>>>>    symtab_node node;
>>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>> -    {
>>>> -      if (symtab_variable_p (node))
>>>> -    return varpool (node);
>>>> -    }
>>>> +    if (varpool_node *vnode = node->try_variable ())
>>>> +      return vnode;
>>>>    return NULL;
>>>>  }
>>>>
>>>> @@ -813,10 +841,8 @@ varpool_next_variable (struct varpool_no
>>>>  {
>>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>>    for (; node1; node1 = node1->symbol.next)
>>>> -    {
>>>> -      if (symtab_variable_p (node1))
>>>> -    return varpool (node1);
>>>> -    }
>>>> +    if (varpool_node *vnode1 = node1->try_variable ())
>>>> +      return vnode1;
>>>>    return NULL;
>>>>  }
>>>>  /* Walk all variables.  */
>>>> @@ -832,9 +858,9 @@ varpool_first_static_initializer (void)
>>>>    symtab_node node;
>>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>>      {
>>>> -      if (symtab_variable_p (node)
>>>> -      && DECL_INITIAL (node->symbol.decl))
>>>> -    return varpool (node);
>>>> +      varpool_node *vnode = node->try_variable ();
>>>> +      if (vnode && DECL_INITIAL (node->symbol.decl))
>>>> +    return vnode;
>>>>      }
>>>>    return NULL;
>>>>  }
>>>> @@ -846,9 +872,9 @@ varpool_next_static_initializer (struct
>>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>>    for (; node1; node1 = node1->symbol.next)
>>>>      {
>>>> -      if (symtab_variable_p (node1)
>>>> -      && DECL_INITIAL (node1->symbol.decl))
>>>> -    return varpool (node1);
>>>> +      varpool_node *vnode1 = node1->try_variable ();
>>>> +      if (vnode1 && DECL_INITIAL (node1->symbol.decl))
>>>> +    return vnode1;
>>>>      }
>>>>    return NULL;
>>>>  }
>>>> @@ -865,8 +891,9 @@ varpool_first_defined_variable (void)
>>>>    symtab_node node;
>>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>>      {
>>>> -      if (symtab_variable_p (node) && varpool (node)->analyzed)
>>>> -    return varpool (node);
>>>> +      varpool_node *vnode = node->try_variable ();
>>>> +      if (vnode && vnode->analyzed)
>>>> +    return vnode;
>>>>      }
>>>>    return NULL;
>>>>  }
>>>> @@ -878,8 +905,9 @@ varpool_next_defined_variable (struct va
>>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>>    for (; node1; node1 = node1->symbol.next)
>>>>      {
>>>> -      if (symtab_variable_p (node1) && varpool (node1)->analyzed)
>>>> -    return varpool (node1);
>>>> +      varpool_node *vnode1 = node1->try_variable ();
>>>> +      if (vnode1 && vnode1->analyzed)
>>>> +    return vnode1;
>>>>      }
>>>>    return NULL;
>>>>  }
>>>> @@ -895,8 +923,9 @@ cgraph_first_defined_function (void)
>>>>    symtab_node node;
>>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>>      {
>>>> -      if (symtab_function_p (node) && cgraph (node)->analyzed)
>>>> -    return cgraph (node);
>>>> +      cgraph_node *cn = node->try_function ();
>>>> +      if (cn && cn->analyzed)
>>>> +    return cn;
>>>>      }
>>>>    return NULL;
>>>>  }
>>>> @@ -908,8 +937,9 @@ cgraph_next_defined_function (struct cgr
>>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>>    for (; node1; node1 = node1->symbol.next)
>>>>      {
>>>> -      if (symtab_function_p (node1) && cgraph (node1)->analyzed)
>>>> -    return cgraph (node1);
>>>> +      cgraph_node *cn1 = node1->try_function ();
>>>> +      if (cn1 && cn1->analyzed)
>>>> +    return cn1;
>>>>      }
>>>>    return NULL;
>>>>  }
>>>> @@ -925,10 +955,8 @@ cgraph_first_function (void)
>>>>  {
>>>>    symtab_node node;
>>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>> -    {
>>>> -      if (symtab_function_p (node))
>>>> -    return cgraph (node);
>>>> -    }
>>>> +    if (cgraph_node *cn = node->try_function ())
>>>> +      return cn;
>>>>    return NULL;
>>>>  }
>>>>
>>>> @@ -938,10 +966,8 @@ cgraph_next_function (struct cgraph_node
>>>>  {
>>>>    symtab_node node1 = (symtab_node) node->symbol.next;
>>>>    for (; node1; node1 = node1->symbol.next)
>>>> -    {
>>>> -      if (symtab_function_p (node1))
>>>> -    return cgraph (node1);
>>>> -    }
>>>> +    if (cgraph_node *cn1 = node1->try_function ())
>>>> +      return cn1;
>>>>    return NULL;
>>>>  }
>>>>  /* Walk all functions.  */
>>>> @@ -968,9 +994,9 @@ cgraph_first_function_with_gimple_body (
>>>>    symtab_node node;
>>>>    for (node = symtab_nodes; node; node = node->symbol.next)
>>>>      {
>>>> -      if (symtab_function_p (node)
>>>> -      && cgraph_function_with_gimple_body_p (cgraph (node)))
>>>> -    return cgraph (node);
>>>> +      cgraph_node *cn = node->try_function ();
>>>> +      if (cn && cgraph_function_with_gimple_body_p (cn))
>>>> +    return cn;
>>>>      }
>>>>    return NULL;
>>>>  }
>>>> @@ -982,9 +1008,9 @@ cgraph_next_function_with_gimple_body (s
>>>>    symtab_node node1 = node->symbol.next;
>>>>    for (; node1; node1 = node1->symbol.next)
>>>>      {
>>>> -      if (symtab_function_p (node1)
>>>> -      && cgraph_function_with_gimple_body_p (cgraph (node1)))
>>>> -    return cgraph (node1);
>>>> +      cgraph_node *cn1 = node1->try_function ();
>>>> +      if (cn1 && cgraph_function_with_gimple_body_p (cn1))
>>>> +    return cn1;
>>>>      }
>>>>    return NULL;
>>>>  }
>>>> @@ -1183,7 +1209,7 @@ cgraph_alias_aliased_node (struct cgraph
>>>>
>>>>    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
>>>>    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
>>>> -  if (symtab_function_p (ref->referred))
>>>> +  if (ref->referred->is_function ())
>>>>      return ipa_ref_node (ref);
>>>>    return NULL;
>>>>  }
>>>> @@ -1197,7 +1223,7 @@ varpool_alias_aliased_node (struct varpo
>>>>
>>>>    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
>>>>    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
>>>> -  if (symtab_variable_p (ref->referred))
>>>> +  if (ref->referred->is_variable ())
>>>>      return ipa_ref_varpool_node (ref);
>>>>    return NULL;
>>>>  }
>>>> @@ -1328,7 +1354,7 @@ symtab_real_symbol_p (symtab_node node)
>>>>    struct cgraph_node *cnode;
>>>>    struct ipa_ref *ref;
>>>>
>>>> -  if (!symtab_function_p (node))
>>>> +  if (!node->is_function ())
>>>>      return true;
>>>>    cnode = cgraph (node);
>>>>    if (cnode->global.inlined_to)
>>>> Index: gcc/tree-emutls.c
>>>> ===================================================================
>>>> --- gcc/tree-emutls.c        (revision 192010)
>>>> +++ gcc/tree-emutls.c        (working copy)
>>>> @@ -260,7 +260,7 @@ get_emutls_init_templ_addr (tree decl)
>>>>    /* Create varpool node for the new variable and finalize it if it is
>>>>       not external one.  */
>>>>    if (DECL_EXTERNAL (to))
>>>> -    varpool_node (to);
>>>> +    varpool_node_for_decl (to);
>>>>    else
>>>>      varpool_add_new_variable (to);
>>>>    return build_fold_addr_expr (to);
>>>> @@ -332,7 +332,7 @@ new_emutls_decl (tree decl, tree alias_o
>>>>    /* Create varpool node for the new variable and finalize it if it is
>>>>       not external one.  */
>>>>    if (DECL_EXTERNAL (to))
>>>> -    varpool_node (to);
>>>> +    varpool_node_for_decl (to);
>>>>    else if (!alias_of)
>>>>      varpool_add_new_variable (to);
>>>>    else
>>>> Index: gcc/ipa-reference.c
>>>> ===================================================================
>>>> --- gcc/ipa-reference.c      (revision 192010)
>>>> +++ gcc/ipa-reference.c      (working copy)
>>>> @@ -482,7 +482,7 @@ analyze_function (struct cgraph_node *fn
>>>>    local = init_function_info (fn);
>>>>    for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list,
>>>> i, ref); i++)
>>>>      {
>>>> -      if (!symtab_variable_p (ref->referred))
>>>> +      if (!ref->referred->is_variable ())
>>>>      continue;
>>>>        var = ipa_ref_varpool_node (ref)->symbol.decl;
>>>>        if (!is_proper_for_analysis (var))
>>>> @@ -979,8 +979,6 @@ stream_out_bitmap (struct lto_simple_out
>>>>  static void
>>>>  ipa_reference_write_optimization_summary (void)
>>>>  {
>>>> -  struct cgraph_node *node;
>>>> -  symtab_node snode;
>>>>    struct lto_simple_output_block *ob
>>>>      = lto_create_simple_output_block (LTO_section_ipa_reference);
>>>>    unsigned int count = 0;
>>>> @@ -994,12 +992,10 @@ ipa_reference_write_optimization_summary
>>>>    /* See what variables we are interested in.  */
>>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>>      {
>>>> -      struct varpool_node *vnode;
>>>> -      snode = lto_symtab_encoder_deref (encoder, i);
>>>> -      if (!symtab_variable_p (snode))
>>>> -    continue;
>>>> -      vnode = varpool (snode);
>>>> -      if (bitmap_bit_p (all_module_statics, DECL_UID
>>>> (vnode->symbol.decl))
>>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> +      varpool_node *vnode = snode->try_variable ();
>>>> +      if (vnode
>>>> +      && bitmap_bit_p (all_module_statics, DECL_UID
>>>> (vnode->symbol.decl))
>>>>        && referenced_from_this_partition_p (&vnode->symbol.ref_list,
>>>> encoder))
>>>>      {
>>>>        tree decl = vnode->symbol.decl;
>>>> @@ -1013,10 +1009,12 @@ ipa_reference_write_optimization_summary
>>>>
>>>>    if (ltrans_statics_bitcount)
>>>>      for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>> -      if (symtab_function_p (snode = lto_symtab_encoder_deref
>>>> (encoder,
>>>> i))
>>>> -      && write_node_summary_p (cgraph (snode),
>>>> -                               encoder, ltrans_statics))
>>>> +      {
>>>> +    symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> +    cgraph_node *cnode = snode->try_function ();
>>>> +    if (cnode && write_node_summary_p (cnode, encoder,
>>>> ltrans_statics))
>>>>        count++;
>>>> +      }
>>>>
>>>>    streamer_write_uhwi_stream (ob->main_stream, count);
>>>>    if (count)
>>>> @@ -1027,17 +1025,15 @@ ipa_reference_write_optimization_summary
>>>>    if (ltrans_statics_bitcount)
>>>>      for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>>        {
>>>> -    snode = lto_symtab_encoder_deref (encoder, i);
>>>> -    if (!symtab_function_p (snode))
>>>> -      continue;
>>>> -    node = cgraph (snode);
>>>> -    if (write_node_summary_p (node, encoder, ltrans_statics))
>>>> +    symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> +    cgraph_node *cnode = snode->try_function ();
>>>> +    if (cnode && write_node_summary_p (cnode, encoder,
>>>> ltrans_statics))
>>>>        {
>>>>          ipa_reference_optimization_summary_t info;
>>>>          int node_ref;
>>>>
>>>> -        info = get_reference_optimization_summary (node);
>>>> -        node_ref = lto_symtab_encoder_encode (encoder, (symtab_node)
>>>> node);
>>>> +        info = get_reference_optimization_summary (cnode);
>>>> +        node_ref = lto_symtab_encoder_encode (encoder, snode);
>>>>          streamer_write_uhwi_stream (ob->main_stream, node_ref);
>>>>
>>>>          stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
>>>> Index: gcc/cgraphunit.c
>>>> ===================================================================
>>>> --- gcc/cgraphunit.c (revision 192010)
>>>> +++ gcc/cgraphunit.c (working copy)
>>>> @@ -386,7 +386,8 @@ referred_to_p (symtab_node node)
>>>>    if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
>>>>      return true;
>>>>    /* For functions check also calls.  */
>>>> -  if (symtab_function_p (node) && cgraph (node)->callers)
>>>> +  cgraph_node *cn = node->try_function ();
>>>> +  if (cn && cn->callers)
>>>>      return true;
>>>>    return false;
>>>>  }
>>>> @@ -809,7 +810,7 @@ process_function_and_variable_attributes
>>>>  void
>>>>  varpool_finalize_decl (tree decl)
>>>>  {
>>>> -  struct varpool_node *node = varpool_node (decl);
>>>> +  struct varpool_node *node = varpool_node_for_decl (decl);
>>>>
>>>>    gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
>>>>
>>>> @@ -836,6 +837,35 @@ varpool_finalize_decl (tree decl)
>>>>      varpool_assemble_decl (node);
>>>>  }
>>>>
>>>> +
>>>> +/* Determine if a symbol is finalized and needed.  */
>>>> +
>>>> +inline static bool
>>>> +symbol_finalized_and_needed (symtab_node node)
>>>> +{
>>>> +  if (cgraph_node *cnode = node->try_function ())
>>>> +    return cnode->local.finalized
>>>> +       && cgraph_decide_is_function_needed (cnode,
>>>> cnode->symbol.decl);
>>>> +  if (varpool_node *vnode = node->try_variable ())
>>>> +    return vnode->finalized
>>>> +       && !DECL_EXTERNAL (vnode->symbol.decl)
>>>> +       && decide_is_variable_needed (vnode, vnode->symbol.decl);
>>>> +  return false;
>>>> +}
>>>> +
>>>> +/* Determine if a symbol is finalized.  */
>>>> +
>>>> +inline static bool
>>>> +symbol_finalized (symtab_node node)
>>>> +{
>>>> +  if (cgraph_node *cnode= node->try_function ())
>>>> +    return cnode->local.finalized;
>>>> +  if (varpool_node *vnode = node->try_variable ())
>>>> +    return vnode->finalized;
>>>> +  return false;
>>>> +}
>>>> +
>>>> +
>>>>  /* Discover all functions and variables that are trivially needed,
>>>> analyze
>>>>     them as well as all functions and variables referred by them  */
>>>>
>>>> @@ -870,13 +900,7 @@ cgraph_analyze_functions (void)
>>>>         node != (symtab_node)first_analyzed
>>>>         && node != (symtab_node)first_analyzed_var; node =
>>>> node->symbol.next)
>>>>      {
>>>> -      if ((symtab_function_p (node)
>>>> -           && cgraph (node)->local.finalized
>>>> -           && cgraph_decide_is_function_needed (cgraph (node),
>>>> node->symbol.decl))
>>>> -          || (symtab_variable_p (node)
>>>> -              && varpool (node)->finalized
>>>> -              && !DECL_EXTERNAL (node->symbol.decl)
>>>> -              && decide_is_variable_needed (varpool (node),
>>>> node->symbol.decl)))
>>>> +      if (symbol_finalized_and_needed (node))
>>>>          {
>>>>            enqueue_node (node);
>>>>            if (!changed && cgraph_dump_file)
>>>> @@ -903,18 +927,15 @@ cgraph_analyze_functions (void)
>>>>        changed = true;
>>>>        node = first;
>>>>        first = (symtab_node)first->symbol.aux;
>>>> -      if (symtab_function_p (node) && cgraph (node)->local.finalized)
>>>> +      cgraph_node *cnode = node->try_function ();
>>>> +      if (cnode && cnode->local.finalized)
>>>>          {
>>>>            struct cgraph_edge *edge;
>>>> -          struct cgraph_node *cnode;
>>>> -          tree decl;
>>>> -
>>>> -          cnode = cgraph (node);
>>>> -          decl = cnode->symbol.decl;
>>>> +          tree decl = cnode->symbol.decl;
>>>>
>>>> -          /* ??? It is possible to create extern inline function and
>>>> later
>>>> using
>>>> -             weak alias attribute to kill its body. See
>>>> -             gcc.c-torture/compile/20011119-1.c  */
>>>> +          /* ??? It is possible to create extern inline function
>>>> +          and later using weak alias attribute to kill its body.
>>>> +          See gcc.c-torture/compile/20011119-1.c  */
>>>>            if (!DECL_STRUCT_FUNCTION (decl)
>>>>                && (!cnode->alias || !cnode->thunk.alias)
>>>>                && !cnode->thunk.thunk_p)
>>>> @@ -929,23 +950,25 @@ cgraph_analyze_functions (void)
>>>>
>>>>            for (edge = cnode->callees; edge; edge = edge->next_callee)
>>>>              if (edge->callee->local.finalized)
>>>> -              enqueue_node ((symtab_node)edge->callee);
>>>> +               enqueue_node ((symtab_node)edge->callee);
>>>>
>>>> -          /* 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.  */
>>>> +          /* 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.  */
>>>>            if (DECL_ABSTRACT_ORIGIN (decl))
>>>>              {
>>>> -              struct cgraph_node *origin_node;
>>>> -              origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN
>>>> (decl));
>>>> +              struct cgraph_node *origin_node
>>>> +              = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
>>>>                origin_node->abstract_and_needed = true;
>>>>              }
>>>> -
>>>>          }
>>>> -      else if (symtab_variable_p (node)
>>>> -               && varpool (node)->finalized)
>>>> -        varpool_analyze_node (varpool (node));
>>>> +      else
>>>> +        {
>>>> +          varpool_node *vnode = node->try_variable ();
>>>> +          if (vnode && vnode->finalized)
>>>> +            varpool_analyze_node (vnode);
>>>> +        }
>>>>
>>>>        if (node->symbol.same_comdat_group)
>>>>          {
>>>> @@ -956,8 +979,7 @@ cgraph_analyze_functions (void)
>>>>              enqueue_node (next);
>>>>          }
>>>>        for (i = 0; ipa_ref_list_reference_iterate
>>>> (&node->symbol.ref_list, i, ref); i++)
>>>> -        if ((symtab_function_p (ref->referred) && cgraph
>>>> (ref->referred)->local.finalized)
>>>> -            || (symtab_variable_p (ref->referred) && varpool
>>>> (ref->referred)->finalized))
>>>> +        if (symbol_finalized (ref->referred))
>>>>            enqueue_node (ref->referred);
>>>>            cgraph_process_new_functions ();
>>>>      }
>>>> @@ -985,10 +1007,9 @@ cgraph_analyze_functions (void)
>>>>        symtab_remove_node (node);
>>>>        continue;
>>>>      }
>>>> -      if (symtab_function_p (node))
>>>> +      if (cgraph_node *cnode = node->try_function ())
>>>>      {
>>>>        tree decl = node->symbol.decl;
>>>> -      struct cgraph_node *cnode = cgraph (node);
>>>>
>>>>        if (cnode->local.finalized && !gimple_has_body_p (decl)
>>>>            && (!cnode->alias || !cnode->thunk.alias)
>>>> @@ -1070,7 +1091,7 @@ handle_alias_pairs (void)
>>>>      }
>>>>
>>>>        if (TREE_CODE (p->decl) == FUNCTION_DECL
>>>> -          && target_node && symtab_function_p (target_node))
>>>> +          && target_node && target_node->is_function ())
>>>>      {
>>>>        struct cgraph_node *src_node = cgraph_get_node (p->decl);
>>>>        if (src_node && src_node->local.finalized)
>>>> @@ -1079,7 +1100,7 @@ handle_alias_pairs (void)
>>>>        VEC_unordered_remove (alias_pair, alias_pairs, i);
>>>>      }
>>>>        else if (TREE_CODE (p->decl) == VAR_DECL
>>>> -           && target_node && symtab_variable_p (target_node))
>>>> +           && target_node && target_node->is_variable ())
>>>>      {
>>>>        varpool_create_variable_alias (p->decl,
>>>> target_node->symbol.decl);
>>>>        VEC_unordered_remove (alias_pair, alias_pairs, i);
>>>> Index: gcc/cp/decl2.c
>>>> ===================================================================
>>>> --- gcc/cp/decl2.c   (revision 192010)
>>>> +++ gcc/cp/decl2.c   (working copy)
>>>> @@ -1778,7 +1778,7 @@ import_export_class (tree ctype)
>>>>  static bool
>>>>  var_finalized_p (tree var)
>>>>  {
>>>> -  return varpool_node (var)->finalized;
>>>> +  return varpool_node_for_decl (var)->finalized;
>>>>  }
>>>>
>>>>  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
>>>> @@ -1896,7 +1896,7 @@ maybe_emit_vtables (tree ctype)
>>>>      TREE_ASM_WRITTEN (vtbl) = 1;
>>>>        else if (DECL_ONE_ONLY (vtbl))
>>>>      {
>>>> -      current = varpool_node (vtbl);
>>>> +      current = varpool_node_for_decl (vtbl);
>>>>        if (last)
>>>>          symtab_add_to_same_comdat_group ((symtab_node) current,
>>>> (symtab_node) last);
>>>>        last = current;
>>>> Index: gcc/ipa-ref.c
>>>> ===================================================================
>>>> --- gcc/ipa-ref.c    (revision 192010)
>>>> +++ gcc/ipa-ref.c    (working copy)
>>>> @@ -42,7 +42,7 @@ ipa_record_reference (symtab_node referr
>>>>    struct ipa_ref_list *list, *list2;
>>>>    VEC(ipa_ref_t,gc) *old_references;
>>>>
>>>> -  gcc_checking_assert (!stmt || symtab_function_p (referring_node));
>>>> +  gcc_checking_assert (!stmt || referring_node->is_function ());
>>>>    gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);
>>>>
>>>>    list = &referring_node->symbol.ref_list;
>>>> Index: gcc/lto-cgraph.c
>>>> ===================================================================
>>>> --- gcc/lto-cgraph.c (revision 192010)
>>>> +++ gcc/lto-cgraph.c (working copy)
>>>> @@ -665,7 +665,7 @@ add_references (lto_symtab_encoder_t enc
>>>>    int i;
>>>>    struct ipa_ref *ref;
>>>>    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
>>>> -    if (symtab_function_p (ref->referred))
>>>> +    if (ref->referred->is_function ())
>>>>        add_node_to (encoder, ipa_ref_node (ref), false);
>>>>      else
>>>>        lto_symtab_encoder_encode (encoder, ref->referred);
>>>> @@ -716,9 +716,8 @@ compute_ltrans_boundary (lto_symtab_enco
>>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>>      {
>>>>        symtab_node node = lto_symtab_encoder_deref (encoder, i);
>>>> -      if (symtab_variable_p (node))
>>>> +      if (varpool_node *vnode = node->try_variable ())
>>>>      {
>>>> -      struct varpool_node *vnode = varpool (node);
>>>>        if (DECL_INITIAL (vnode->symbol.decl)
>>>>            && !lto_symtab_encoder_encode_initializer_p (encoder,
>>>>                                                         vnode)
>>>> @@ -782,8 +781,8 @@ output_symtab (void)
>>>>    for (i = 0; i < n_nodes; i++)
>>>>      {
>>>>        symtab_node node = lto_symtab_encoder_deref (encoder, i);
>>>> -      if (symtab_function_p (node))
>>>> -        lto_output_node (ob, cgraph (node), encoder);
>>>> +      if (cgraph_node *cnode = node->try_function ())
>>>> +        lto_output_node (ob, cnode, encoder);
>>>>        else
>>>>          lto_output_varpool_node (ob, varpool (node), encoder);
>>>>
>>>> @@ -969,7 +968,7 @@ input_varpool_node (struct lto_file_decl
>>>>    order = streamer_read_hwi (ib) + order_base;
>>>>    decl_index = streamer_read_uhwi (ib);
>>>>    var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
>>>> -  node = varpool_node (var_decl);
>>>> +  node = varpool_node_for_decl (var_decl);
>>>>    node->symbol.order = order;
>>>>    if (order >= symtab_order)
>>>>      symtab_order = order + 1;
>>>> @@ -1130,14 +1129,14 @@ input_cgraph_1 (struct lto_file_decl_dat
>>>>    /* AUX pointers should be all non-zero for function nodes read from
>>>> the stream.  */
>>>>  #ifdef ENABLE_CHECKING
>>>>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>>>> -    gcc_assert (node->symbol.aux || !symtab_function_p (node));
>>>> +    gcc_assert (node->symbol.aux || !node->is_function ());
>>>>  #endif
>>>>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>>>>      {
>>>>        int ref;
>>>> -      if (symtab_function_p (node))
>>>> +      if (cgraph_node *cnode = node->try_function ())
>>>>      {
>>>> -      ref = (int) (intptr_t) cgraph (node)->global.inlined_to;
>>>> +      ref = (int) (intptr_t) cnode->global.inlined_to;
>>>>
>>>>        /* We share declaration of builtins, so we may read same node
>>>> twice.
>>>> */
>>>>        if (!node->symbol.aux)
>>>> @@ -1146,9 +1145,9 @@ input_cgraph_1 (struct lto_file_decl_dat
>>>>
>>>>        /* Fixup inlined_to from reference to pointer.  */
>>>>        if (ref != LCC_NOT_FOUND)
>>>> -        cgraph (node)->global.inlined_to = cgraph (VEC_index
>>>> (symtab_node, nodes, ref));
>>>> +        cnode->global.inlined_to = cgraph (VEC_index (symtab_node,
>>>> nodes,
>>>> ref));
>>>>        else
>>>> -        cgraph (node)->global.inlined_to = NULL;
>>>> +        cnode->global.inlined_to = NULL;
>>>>      }
>>>>
>>>>        ref = (int) (intptr_t) node->symbol.same_comdat_group;
>>>> @@ -1160,7 +1159,7 @@ input_cgraph_1 (struct lto_file_decl_dat
>>>>      node->symbol.same_comdat_group = NULL;
>>>>      }
>>>>    FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
>>>> -    node->symbol.aux = symtab_function_p (node) ? (void *)1 : NULL;
>>>> +    node->symbol.aux = node->is_function () ? (void *)1 : NULL;
>>>>    return nodes;
>>>>  }
>>>>
>>>> @@ -1435,7 +1434,6 @@ output_node_opt_summary (struct output_b
>>>>  static void
>>>>  output_cgraph_opt_summary (void)
>>>>  {
>>>> -  symtab_node node;
>>>>    int i, n_nodes;
>>>>    lto_symtab_encoder_t encoder;
>>>>    struct output_block *ob = create_output_block
>>>> (LTO_section_cgraph_opt_sum);
>>>> @@ -1445,18 +1443,21 @@ output_cgraph_opt_summary (void)
>>>>    encoder = ob->decl_state->symtab_node_encoder;
>>>>    n_nodes = lto_symtab_encoder_size (encoder);
>>>>    for (i = 0; i < n_nodes; i++)
>>>> -    if (symtab_function_p (node = lto_symtab_encoder_deref (encoder,
>>>> i))
>>>> -    && output_cgraph_opt_summary_p (cgraph (node)))
>>>> -      count++;
>>>> +    {
>>>> +      symtab_node node = lto_symtab_encoder_deref (encoder, i);
>>>> +      cgraph_node *cnode = node->try_function ();
>>>> +      if (cnode && output_cgraph_opt_summary_p (cnode))
>>>> +    count++;
>>>> +    }
>>>>    streamer_write_uhwi (ob, count);
>>>>    for (i = 0; i < n_nodes; i++)
>>>>      {
>>>> -      node = lto_symtab_encoder_deref (encoder, i);
>>>> -      if (symtab_function_p (node)
>>>> -      && output_cgraph_opt_summary_p (cgraph (node)))
>>>> +      symtab_node node = lto_symtab_encoder_deref (encoder, i);
>>>> +      cgraph_node *cnode = node->try_function ();
>>>> +      if (cnode && output_cgraph_opt_summary_p (cnode))
>>>>      {
>>>>        streamer_write_uhwi (ob, i);
>>>> -      output_node_opt_summary (ob, cgraph (node), encoder);
>>>> +      output_node_opt_summary (ob, cnode, encoder);
>>>>      }
>>>>      }
>>>>    produce_asm (ob, NULL);
>>>> Index: gcc/lto-streamer-out.c
>>>> ===================================================================
>>>> --- gcc/lto-streamer-out.c   (revision 192010)
>>>> +++ gcc/lto-streamer-out.c   (working copy)
>>>> @@ -972,7 +972,6 @@ copy_function (struct cgraph_node *node)
>>>>  static void
>>>>  lto_output (void)
>>>>  {
>>>> -  struct cgraph_node *node;
>>>>    struct lto_out_decl_state *decl_state;
>>>>  #ifdef ENABLE_CHECKING
>>>>    bitmap output = lto_bitmap_alloc ();
>>>> @@ -988,10 +987,9 @@ lto_output (void)
>>>>    for (i = 0; i < n_nodes; i++)
>>>>      {
>>>>        symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> -      if (!symtab_function_p (snode))
>>>> -    continue;
>>>> -      node = cgraph (snode);
>>>> -      if (lto_symtab_encoder_encode_body_p (encoder, node)
>>>> +      cgraph_node *node = snode->try_function ();
>>>> +      if (node
>>>> +      && lto_symtab_encoder_encode_body_p (encoder, node)
>>>>        && !node->alias
>>>>        && !node->thunk.thunk_p)
>>>>      {
>>>> @@ -1285,8 +1283,6 @@ produce_symtab (struct output_block *ob)
>>>>    struct streamer_tree_cache_d *cache = ob->writer_cache;
>>>>    char *section_name = lto_get_section_name (LTO_section_symtab, NULL,
>>>> NULL);
>>>>    struct pointer_set_t *seen;
>>>> -  struct cgraph_node *node;
>>>> -  struct varpool_node *vnode;
>>>>    struct lto_output_stream stream;
>>>>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>>>>    int i;
>>>> @@ -1302,49 +1298,52 @@ produce_symtab (struct output_block *ob)
>>>>       This is done so only to handle duplicated symbols in cgraph.  */
>>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>>      {
>>>> -      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
>>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> +      cgraph_node *cnode = snode->try_function ();
>>>> +      if (!cnode)
>>>>      continue;
>>>> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
>>>> -      if (DECL_EXTERNAL (node->symbol.decl))
>>>> +      if (DECL_EXTERNAL (cnode->symbol.decl))
>>>>      continue;
>>>> -      if (DECL_COMDAT (node->symbol.decl)
>>>> -      && cgraph_comdat_can_be_unshared_p (node))
>>>> +      if (DECL_COMDAT (cnode->symbol.decl)
>>>> +      && cgraph_comdat_can_be_unshared_p (cnode))
>>>>      continue;
>>>> -      if ((node->alias && !node->thunk.alias) ||
>>>> node->global.inlined_to)
>>>> +      if ((cnode->alias && !cnode->thunk.alias) ||
>>>> cnode->global.inlined_to)
>>>>      continue;
>>>> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
>>>> +      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
>>>>      }
>>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>>      {
>>>> -      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
>>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> +      cgraph_node *cnode = snode->try_function ();
>>>> +      if (!cnode)
>>>>      continue;
>>>> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
>>>> -      if (!DECL_EXTERNAL (node->symbol.decl))
>>>> +      if (!DECL_EXTERNAL (cnode->symbol.decl))
>>>>      continue;
>>>>        /* We keep around unused extern inlines in order to be able to
>>>> inline
>>>>       them indirectly or via vtables.  Do not output them to symbol
>>>>       table: they end up being undefined and just consume space.  */
>>>> -      if (!node->symbol.address_taken && !node->callers)
>>>> +      if (!cnode->symbol.address_taken && !cnode->callers)
>>>>      continue;
>>>> -      if (DECL_COMDAT (node->symbol.decl)
>>>> -      && cgraph_comdat_can_be_unshared_p (node))
>>>> +      if (DECL_COMDAT (cnode->symbol.decl)
>>>> +      && cgraph_comdat_can_be_unshared_p (cnode))
>>>>      continue;
>>>> -      if ((node->alias && !node->thunk.alias) ||
>>>> node->global.inlined_to)
>>>> +      if ((cnode->alias && !cnode->thunk.alias) ||
>>>> cnode->global.inlined_to)
>>>>      continue;
>>>> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
>>>> +      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
>>>>      }
>>>>
>>>>    /* Write all variables.  */
>>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>>      {
>>>> -      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
>>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> +      varpool_node *vnode = snode->try_variable ();
>>>> +      if (!vnode)
>>>>      continue;
>>>> -      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
>>>>        if (DECL_EXTERNAL (vnode->symbol.decl))
>>>>      continue;
>>>>        /* COMDAT virtual tables can be unshared.  Do not declare them
>>>> -     in the LTO symbol table to prevent linker from forcing them
>>>> -     into the output. */
>>>> +    in the LTO symbol table to prevent linker from forcing them
>>>> +    into the output. */
>>>>        if (DECL_COMDAT (vnode->symbol.decl)
>>>>        && !vnode->symbol.force_output
>>>>        && vnode->finalized
>>>> @@ -1356,9 +1355,10 @@ produce_symtab (struct output_block *ob)
>>>>      }
>>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>>      {
>>>> -      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
>>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> +      varpool_node *vnode = snode->try_variable ();
>>>> +      if (!vnode)
>>>>      continue;
>>>> -      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
>>>>        if (!DECL_EXTERNAL (vnode->symbol.decl))
>>>>      continue;
>>>>        if (DECL_COMDAT (vnode->symbol.decl)
>>>> Index: gcc/ada/gcc-interface/utils.c
>>>> ===================================================================
>>>> --- gcc/ada/gcc-interface/utils.c    (revision 192010)
>>>> +++ gcc/ada/gcc-interface/utils.c    (working copy)
>>>> @@ -5582,7 +5582,7 @@ gnat_write_global_declarations (void)
>>>>                    void_type_node);
>>>>        TREE_STATIC (dummy_global) = 1;
>>>>        TREE_ASM_WRITTEN (dummy_global) = 1;
>>>> -      node = varpool_node (dummy_global);
>>>> +      node = varpool_node_for_decl (dummy_global);
>>>>        node->symbol.force_output = 1;
>>>>
>>>>        while (!VEC_empty (tree, types_used_by_cur_var_decl))
>>>> Index: gcc/ipa.c
>>>> ===================================================================
>>>> --- gcc/ipa.c        (revision 192010)
>>>> +++ gcc/ipa.c        (working copy)
>>>> @@ -84,7 +84,7 @@ process_references (struct ipa_ref_list
>>>>    struct ipa_ref *ref;
>>>>    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
>>>>      {
>>>> -      if (symtab_function_p (ref->referred))
>>>> +      if (ref->referred->is_function ())
>>>>      {
>>>>        struct cgraph_node *node = ipa_ref_node (ref);
>>>>
>>>> @@ -290,10 +290,8 @@ symtab_remove_unreachable_nodes (bool be
>>>>                            before_inlining_p, reachable);
>>>>      }
>>>>
>>>> -      if (symtab_function_p (node))
>>>> +      if (cgraph_node *cnode = node->try_function ())
>>>>      {
>>>> -      struct cgraph_node *cnode = cgraph (node);
>>>> -
>>>>        /* Mark the callees reachable unless they are direct calls to
>>>> extern
>>>>           inline functions we decided to not inline.  */
>>>>        if (!in_boundary_p)
>>>> @@ -332,18 +330,18 @@ symtab_remove_unreachable_nodes (bool be
>>>>          }
>>>>      }
>>>>        /* When we see constructor of external variable, keep referred
>>>> nodes in the
>>>> -     boundary.  This will also hold initializers of the external vars
>>>> NODE
>>>> -     reffers to.  */
>>>> -      if (symtab_variable_p (node)
>>>> +    boundary.  This will also hold initializers of the external vars
>>>> NODE
>>>> +    refers to.  */
>>>> +      varpool_node *vnode = node->try_variable ();
>>>> +      if (vnode
>>>>        && DECL_EXTERNAL (node->symbol.decl)
>>>> -      && !varpool (node)->alias
>>>> +      && !vnode->alias
>>>>        && in_boundary_p)
>>>> -        {
>>>> -      int i;
>>>> +    {
>>>>        struct ipa_ref *ref;
>>>> -      for (i = 0; ipa_ref_list_reference_iterate
>>>> (&node->symbol.ref_list, i, ref); i++)
>>>> +      for (int i = 0; ipa_ref_list_reference_iterate
>>>> (&node->symbol.ref_list, i, ref); i++)
>>>>          enqueue_node (ref->referred, &first, reachable);
>>>> -        }
>>>> +    }
>>>>      }
>>>>
>>>>    /* Remove unreachable functions.   */
>>>> @@ -526,7 +524,7 @@ cgraph_address_taken_from_non_vtable_p (
>>>>      if (ref->use == IPA_REF_ADDR)
>>>>        {
>>>>      struct varpool_node *node;
>>>> -    if (symtab_function_p (ref->referring))
>>>> +    if (ref->referring->is_function ())
>>>>        return true;
>>>>      node = ipa_ref_referring_varpool_node (ref);
>>>>      if (!DECL_VIRTUAL_P (node->symbol.decl))
>>>> Index: gcc/ipa-inline-analysis.c
>>>> ===================================================================
>>>> --- gcc/ipa-inline-analysis.c        (revision 192010)
>>>> +++ gcc/ipa-inline-analysis.c        (working copy)
>>>> @@ -3811,22 +3811,25 @@ void
>>>>  inline_write_summary (void)
>>>>  {
>>>>    struct cgraph_node *node;
>>>> -  symtab_node snode;
>>>>    struct output_block *ob = create_output_block
>>>> (LTO_section_inline_summary);
>>>>    lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
>>>>    unsigned int count = 0;
>>>>    int i;
>>>>
>>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>> -    if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder,
>>>> i))
>>>> -    && cgraph (snode)->analyzed)
>>>> -      count++;
>>>> +    {
>>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> +      cgraph_node *cnode = snode->try_function ();
>>>> +      if (cnode && cnode->analyzed)
>>>> +    count++;
>>>> +    }
>>>>    streamer_write_uhwi (ob, count);
>>>>
>>>>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>>>>      {
>>>> -      if (symtab_function_p (snode = lto_symtab_encoder_deref
>>>> (encoder,
>>>> i))
>>>> -      && (node = cgraph (snode))->analyzed)
>>>> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
>>>> +      cgraph_node *cnode = snode->try_function ();
>>>> +      if (cnode && (node = cnode)->analyzed)
>>>>      {
>>>>        struct inline_summary *info = inline_summary (node);
>>>>        struct bitpack_d bp;
>>>> @@ -3834,7 +3837,7 @@ inline_write_summary (void)
>>>>        int i;
>>>>        size_time_entry *e;
>>>>        struct condition *c;
>>>> -
>>>> +
>>>>        streamer_write_uhwi (ob, lto_symtab_encoder_encode (encoder,
>>>> (symtab_node)node));
>>>>        streamer_write_hwi (ob, info->estimated_self_stack_size);
>>>>        streamer_write_hwi (ob, info->self_size);
>>>> @@ -3853,7 +3856,7 @@ inline_write_summary (void)
>>>>            bp_pack_value (&bp, c->by_ref, 1);
>>>>            streamer_write_bitpack (&bp);
>>>>            if (c->agg_contents)
>>>> -            streamer_write_uhwi (ob, c->offset);
>>>> +            streamer_write_uhwi (ob, c->offset);
>>>>          }
>>>>        streamer_write_uhwi (ob, VEC_length (size_time_entry,
>>>> info->entry));
>>>>        for (i = 0;
>>>> Index: gcc/lto/lto.c
>>>> ===================================================================
>>>> --- gcc/lto/lto.c    (revision 192010)
>>>> +++ gcc/lto/lto.c    (working copy)
>>>> @@ -2620,12 +2620,17 @@ lto_wpa_write_files (void)
>>>>            if (!lto_symtab_encoder_in_partition_p (part->encoder,
>>>> node))
>>>>              {
>>>>                fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name
>>>> (node));
>>>> -              if (symtab_function_p (node)
>>>> -                  && lto_symtab_encoder_encode_body_p (part->encoder,
>>>> cgraph
>>>> (node)))
>>>> +              cgraph_node *cnode = node->try_function ();
>>>> +              if (cnode
>>>> +                  && lto_symtab_encoder_encode_body_p (part->encoder,
>>>> cnode))
>>>>                  fprintf (cgraph_dump_file, "(body included)");
>>>> -              else if (symtab_variable_p (node)
>>>> -                       && lto_symtab_encoder_encode_initializer_p
>>>> (part->encoder, varpool (node)))
>>>> -                fprintf (cgraph_dump_file, "(initializer included)");
>>>> +              else
>>>> +                {
>>>> +                  varpool_node *vnode = node->try_variable ();
>>>> +                  if (vnode
>>>> +                      && lto_symtab_encoder_encode_initializer_p
>>>> (part->encoder, vnode))
>>>> +                    fprintf (cgraph_dump_file, "(initializer
>>>> included)");
>>>> +                }
>>>>              }
>>>>          }
>>>>        fprintf (cgraph_dump_file, "\n");
>>>> Index: gcc/lto/lto-partition.c
>>>> ===================================================================
>>>> --- gcc/lto/lto-partition.c  (revision 192010)
>>>> +++ gcc/lto/lto-partition.c  (working copy)
>>>> @@ -55,22 +55,22 @@ get_symbol_class (symtab_node node)
>>>>  {
>>>>    /* Inline clones are always duplicated.
>>>>       This include external delcarations.   */
>>>> -  if (symtab_function_p (node)
>>>> -      && cgraph (node)->global.inlined_to)
>>>> +  cgraph_node *cnode = node->try_function ();
>>>> +  if (cnode && cnode->global.inlined_to)
>>>>      return SYMBOL_DUPLICATE;
>>>>
>>>>    /* External declarations are external.  */
>>>>    if (DECL_EXTERNAL (node->symbol.decl))
>>>>      return SYMBOL_EXTERNAL;
>>>>
>>>> -  if (symtab_variable_p (node))
>>>> +  if (varpool_node *vnode = node->try_variable ())
>>>>      {
>>>>        /* Constant pool references use local symbol names that can not
>>>>           be promoted global.  We should never put into a constant pool
>>>>           objects that can not be duplicated across partitions.  */
>>>>        if (DECL_IN_CONSTANT_POOL (node->symbol.decl))
>>>>      return SYMBOL_DUPLICATE;
>>>> -      gcc_checking_assert (varpool (node)->analyzed);
>>>> +      gcc_checking_assert (vnode->analyzed);
>>>>      }
>>>>    /* Functions that are cloned may stay in callgraph even if they are
>>>> unused.
>>>>       Handle them as external; compute_ltrans_boundary take care to
>>>> make
>>>> @@ -145,7 +145,7 @@ add_references_to_partition (ltrans_part
>>>>      /* References to a readonly variable may be constant foled into
>>>> its
>>>> value.
>>>>         Recursively look into the initializers of the constant variable
>>>> and add
>>>>         references, too.  */
>>>> -    else if (symtab_variable_p (ref->referred)
>>>> +    else if (ref->referred->is_variable ()
>>>>           && const_value_known_p (ref->referred->symbol.decl)
>>>>           && !lto_symtab_encoder_in_partition_p (part->encoder,
>>>> ref->referred))
>>>>        {
>>>> @@ -196,9 +196,8 @@ add_symbol_to_partition_1 (ltrans_partit
>>>>      }
>>>>    node->symbol.aux = (void *)((size_t)node->symbol.aux + 1);
>>>>
>>>> -  if (symtab_function_p (node))
>>>> +  if (cgraph_node *cnode = node->try_function ())
>>>>      {
>>>> -      struct cgraph_node *cnode = cgraph (node);
>>>>        struct cgraph_edge *e;
>>>>        part->insns += inline_summary (cnode)->self_size;
>>>>
>>>> @@ -247,15 +246,15 @@ contained_in_symbol (symtab_node node)
>>>>    if (lookup_attribute ("weakref",
>>>>                      DECL_ATTRIBUTES (node->symbol.decl)))
>>>>      return node;
>>>> -  if (symtab_function_p (node))
>>>> +  if (cgraph_node *cnode = node->try_function ())
>>>>      {
>>>> -      struct cgraph_node *cnode = cgraph_function_node (cgraph (node),
>>>> NULL);
>>>> +      cnode = cgraph_function_node (cnode, NULL);
>>>>        if (cnode->global.inlined_to)
>>>>      cnode = cnode->global.inlined_to;
>>>>        return (symtab_node) cnode;
>>>>      }
>>>> -  else if (symtab_variable_p (node))
>>>> -    return (symtab_node) varpool_variable_node (varpool (node), NULL);
>>>> +  else if (varpool_node *vnode = node->try_variable ())
>>>> +    return (symtab_node) varpool_variable_node (vnode, NULL);
>>>>    return node;
>>>>  }
>>>>
>>>> @@ -302,8 +301,8 @@ undo_partition (ltrans_partition partiti
>>>>      pointer_set_destroy (partition->initializers_visited);
>>>>        partition->initializers_visited = NULL;
>>>>
>>>> -      if (symtab_function_p (node))
>>>> -        partition->insns -= inline_summary (cgraph (node))->self_size;
>>>> +      if (cgraph_node *cnode = node->try_function ())
>>>> +        partition->insns -= inline_summary (cnode)->self_size;
>>>>        lto_symtab_encoder_delete_node (partition->encoder, node);
>>>>        node->symbol.aux = (void *)((size_t)node->symbol.aux - 1);
>>>>      }
>>>> @@ -555,11 +554,10 @@ lto_balanced_map (void)
>>>>        symtab_node snode = lto_symtab_encoder_deref
>>>> (partition->encoder,
>>>>
>>>> last_visited_node);
>>>>
>>>> -      if (symtab_function_p (snode))
>>>> +      if (cgraph_node *node = snode->try_function ())
>>>>          {
>>>>            struct cgraph_edge *edge;
>>>>
>>>> -          node = cgraph (snode);
>>>>            refs = &node->symbol.ref_list;
>>>>
>>>>            last_visited_node++;
>>>> @@ -611,7 +609,7 @@ lto_balanced_map (void)
>>>>        /* Compute boundary cost of IPA REF edges and at the same time
>>>> look
>>>> into
>>>>           variables referenced from current partition and try to add
>>>> them.
>>>> */
>>>>        for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++)
>>>> -        if (symtab_variable_p (ref->referred))
>>>> +        if (ref->referred->is_variable ())
>>>>            {
>>>>              int index;
>>>>
>>>> @@ -645,7 +643,7 @@ lto_balanced_map (void)
>>>>                cost++;
>>>>            }
>>>>        for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++)
>>>> -        if (symtab_variable_p (ref->referring))
>>>> +        if (ref->referring->is_variable ())
>>>>            {
>>>>              int index;
>>>>
>>>> Index: gcc/varasm.c
>>>> ===================================================================
>>>> --- gcc/varasm.c     (revision 192010)
>>>> +++ gcc/varasm.c     (working copy)
>>>> @@ -2221,7 +2221,7 @@ mark_decl_referenced (tree decl)
>>>>      }
>>>>    else if (TREE_CODE (decl) == VAR_DECL)
>>>>      {
>>>> -      struct varpool_node *node = varpool_node (decl);
>>>> +      struct varpool_node *node = varpool_node_for_decl (decl);
>>>>        /* C++ frontend use mark_decl_references to force COMDAT
>>>> variables
>>>>           to be output that might appear dead otherwise.  */
>>>>        node->symbol.force_output = true;
>>>> @@ -5549,7 +5549,7 @@ assemble_alias (tree decl, tree target)
>>>>    if (TREE_CODE (decl) == FUNCTION_DECL)
>>>>      cgraph_get_create_node (decl)->alias = true;
>>>>    else
>>>> -    varpool_node (decl)->alias = true;
>>>> +    varpool_node_for_decl (decl)->alias = true;
>>>>
>>>>    /* If the target has already been emitted, we don't have to queue
>>>> the
>>>>       alias.  This saves a tad of memory.  */
>>>> Index: gcc/symtab.c
>>>> ===================================================================
>>>> --- gcc/symtab.c     (revision 192010)
>>>> +++ gcc/symtab.c     (working copy)
>>>> @@ -104,7 +104,7 @@ eq_assembler_name (const void *p1, const
>>>>  static void
>>>>  insert_to_assembler_name_hash (symtab_node node)
>>>>  {
>>>> -  if (symtab_variable_p (node) && DECL_HARD_REGISTER
>>>> (node->symbol.decl))
>>>> +  if (node->is_variable () && DECL_HARD_REGISTER (node->symbol.decl))
>>>>      return;
>>>>    gcc_checking_assert (!node->symbol.previous_sharing_asm_name
>>>>                     && !node->symbol.next_sharing_asm_name);
>>>> @@ -252,8 +252,8 @@ symtab_unregister_node (symtab_node node
>>>>    if (*slot == node)
>>>>      {
>>>>        symtab_node replacement_node = NULL;
>>>> -      if (symtab_function_p (node))
>>>> -    replacement_node = (symtab_node)cgraph_find_replacement_node
>>>> (cgraph
>>>> (node));
>>>> +      if (cgraph_node *cnode = node->try_function ())
>>>> +    replacement_node = (symtab_node)cgraph_find_replacement_node
>>>> (cnode);
>>>>        if (!replacement_node)
>>>>      htab_clear_slot (symtab_hash, slot);
>>>>        else
>>>> @@ -294,10 +294,10 @@ symtab_get_node (const_tree decl)
>>>>  void
>>>>  symtab_remove_node (symtab_node node)
>>>>  {
>>>> -  if (symtab_function_p (node))
>>>> -    cgraph_remove_node (cgraph (node));
>>>> -  else if (symtab_variable_p (node))
>>>> -    varpool_remove_node (varpool (node));
>>>> +  if (cgraph_node *cnode = node->try_function ())
>>>> +    cgraph_remove_node (cnode);
>>>> +  else if (varpool_node *vnode = node->try_variable ())
>>>> +    varpool_remove_node (vnode);
>>>>  }
>>>>
>>>>  /* Initalize asm name hash unless.  */
>>>> @@ -538,10 +538,10 @@ dump_symtab_base (FILE *f, symtab_node n
>>>>  void
>>>>  dump_symtab_node (FILE *f, symtab_node node)
>>>>  {
>>>> -  if (symtab_function_p (node))
>>>> -    dump_cgraph_node (f, cgraph (node));
>>>> -  else if (symtab_variable_p (node))
>>>> -    dump_varpool_node (f, varpool (node));
>>>> +  if (cgraph_node *cnode = node->try_function ())
>>>> +    dump_cgraph_node (f, cnode);
>>>> +  else if (varpool_node *vnode = node->try_variable ())
>>>> +    dump_varpool_node (f, vnode);
>>>>  }
>>>>
>>>>  /* Dump symbol table.  */
>>>> @@ -579,7 +579,7 @@ verify_symtab_base (symtab_node node)
>>>>    bool error_found = false;
>>>>    symtab_node hashed_node;
>>>>
>>>> -  if (symtab_function_p (node))
>>>> +  if (node->is_function ())
>>>>      {
>>>>        if (TREE_CODE (node->symbol.decl) != FUNCTION_DECL)
>>>>      {
>>>> @@ -587,7 +587,7 @@ verify_symtab_base (symtab_node node)
>>>>            error_found = true;
>>>>      }
>>>>      }
>>>> -  else if (symtab_variable_p (node))
>>>> +  else if (node->is_variable ())
>>>>      {
>>>>        if (TREE_CODE (node->symbol.decl) != VAR_DECL)
>>>>      {
>>>> @@ -622,7 +622,7 @@ verify_symtab_base (symtab_node node)
>>>>        hashed_node = hashed_node->symbol.next_sharing_asm_name;
>>>>      }
>>>>        if (!hashed_node
>>>> -          && !(symtab_variable_p (node) || DECL_HARD_REGISTER
>>>> (node->symbol.decl)))
>>>> +          && !(node->is_variable () || DECL_HARD_REGISTER
>>>> (node->symbol.decl)))
>>>>      {
>>>>            error ("node not found in symtab assembler name hash");
>>>>            error_found = true;
>>>> @@ -676,8 +676,8 @@ verify_symtab_node (symtab_node node)
>>>>      return;
>>>>
>>>>    timevar_push (TV_CGRAPH_VERIFY);
>>>> -  if (symtab_function_p (node))
>>>> -    verify_cgraph_node (cgraph (node));
>>>> +  if (cgraph_node *cnode = node->try_function ())
>>>> +    verify_cgraph_node (cnode);
>>>>    else
>>>>      if (verify_symtab_base (node))
>>>>        {
>>>> Index: gcc/passes.c
>>>> ===================================================================
>>>> --- gcc/passes.c     (revision 192010)
>>>> +++ gcc/passes.c     (working copy)
>>>> @@ -201,7 +201,7 @@ rest_of_decl_compilation (tree decl,
>>>>      ;
>>>>    else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)
>>>>         && TREE_STATIC (decl))
>>>> -    varpool_node (decl);
>>>> +    varpool_node_for_decl (decl);
>>>>  }
>>>>
>>>>  /* Called after finishing a record, union or enumeral type.  */
>>>> Index: gcc/varpool.c
>>>> ===================================================================
>>>> --- gcc/varpool.c    (revision 192010)
>>>> +++ gcc/varpool.c    (working copy)
>>>> @@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.
>>>>
>>>>  /* Return varpool node assigned to DECL.  Create new one when needed.
>>>> */
>>>>  struct varpool_node *
>>>> -varpool_node (tree decl)
>>>> +varpool_node_for_decl (tree decl)
>>>>  {
>>>>    struct varpool_node *node = varpool_get_node (decl);
>>>>    gcc_assert (TREE_CODE (decl) == VAR_DECL
>>>> @@ -114,9 +114,9 @@ debug_varpool (void)
>>>>  struct varpool_node *
>>>>  varpool_node_for_asm (tree asmname)
>>>>  {
>>>> -  symtab_node node = symtab_node_for_asm (asmname);
>>>> -  if (node && symtab_variable_p (node))
>>>> -    return varpool (node);
>>>> +  if (symtab_node node = symtab_node_for_asm (asmname))
>>>> +    if (varpool_node *vnode = node->try_variable ())
>>>> +      return vnode;
>>>>    return NULL;
>>>>  }
>>>>
>>>> @@ -192,7 +192,7 @@ varpool_add_new_variable (tree decl)
>>>>  {
>>>>    struct varpool_node *node;
>>>>    varpool_finalize_decl (decl);
>>>> -  node = varpool_node (decl);
>>>> +  node = varpool_node_for_decl (decl);
>>>>    if (varpool_externally_visible_p (node, false))
>>>>      node->symbol.externally_visible = true;
>>>>  }
>>>> @@ -232,7 +232,7 @@ varpool_analyze_node (struct varpool_nod
>>>>      }
>>>>    if (node->alias && node->alias_of)
>>>>      {
>>>> -      struct varpool_node *tgt = varpool_node (node->alias_of);
>>>> +      struct varpool_node *tgt = varpool_node_for_decl
>>>> (node->alias_of);
>>>>        struct varpool_node *n;
>>>>
>>>>        for (n = tgt; n && n->alias;
>>>> @@ -378,16 +378,21 @@ varpool_remove_unreferenced_decls (void)
>>>>        for (next = node->symbol.same_comdat_group;
>>>>             next != (symtab_node)node;
>>>>             next = next->symbol.same_comdat_group)
>>>> -        if (symtab_variable_p (next)
>>>> -            && varpool (next)->analyzed)
>>>> -          enqueue_node (varpool (next), &first);
>>>> +        {
>>>> +          varpool_node *vnext = next->try_variable ();
>>>> +          if (vnext && vnext->analyzed)
>>>> +            enqueue_node (vnext, &first);
>>>> +        }
>>>>      }
>>>>        for (i = 0; ipa_ref_list_reference_iterate
>>>> (&node->symbol.ref_list, i, ref); i++)
>>>> -    if (symtab_variable_p (ref->referred)
>>>> -        && (!DECL_EXTERNAL (ref->referred->symbol.decl)
>>>> -            || varpool (ref->referred)->alias)
>>>> -        && varpool (ref->referred)->analyzed)
>>>> -      enqueue_node (varpool (ref->referred), &first);
>>>> +    {
>>>> +      varpool_node *vnode = ref->referred->try_variable ();
>>>> +      if (vnode
>>>> +          && (!DECL_EXTERNAL (ref->referred->symbol.decl)
>>>> +              || vnode->alias)
>>>> +          && vnode->analyzed)
>>>> +        enqueue_node (vnode, &first);
>>>> +    }
>>>>      }
>>>>    if (cgraph_dump_file)
>>>>      fprintf (cgraph_dump_file, "\nRemoving variables:");
>>>> @@ -461,7 +466,7 @@ add_new_static_var (tree type)
>>>>    DECL_CONTEXT (new_decl) = NULL_TREE;
>>>>    DECL_ABSTRACT (new_decl) = 0;
>>>>    lang_hooks.dup_lang_specific_decl (new_decl);
>>>> -  new_node = varpool_node (new_decl);
>>>> +  new_node = varpool_node_for_decl (new_decl);
>>>>    varpool_finalize_decl (new_decl);
>>>>
>>>>    return new_node->symbol.decl;
>>>> @@ -477,7 +482,7 @@ varpool_create_variable_alias (tree alia
>>>>
>>>>    gcc_assert (TREE_CODE (decl) == VAR_DECL);
>>>>    gcc_assert (TREE_CODE (alias) == VAR_DECL);
>>>> -  alias_node = varpool_node (alias);
>>>> +  alias_node = varpool_node_for_decl (alias);
>>>>    alias_node->alias = 1;
>>>>    alias_node->finalized = 1;
>>>>    alias_node->alias_of = decl;
>>>> Index: gcc/lto-streamer.h
>>>> ===================================================================
>>>> --- gcc/lto-streamer.h       (revision 192010)
>>>> +++ gcc/lto-streamer.h       (working copy)
>>>> @@ -1120,7 +1120,7 @@ lsei_next_function_in_partition (lto_sym
>>>>  {
>>>>    lsei_next (lsei);
>>>>    while (!lsei_end_p (*lsei)
>>>> -     && (!symtab_function_p (lsei_node (*lsei))
>>>> +     && (!lsei_node (*lsei)->is_function ()
>>>>           || !lto_symtab_encoder_in_partition_p (lsei->encoder,
>>>> lsei_node
>>>> (*lsei))))
>>>>      lsei_next (lsei);
>>>>  }
>>>> @@ -1133,7 +1133,7 @@ lsei_start_function_in_partition (lto_sy
>>>>
>>>>    if (lsei_end_p (lsei))
>>>>      return lsei;
>>>> -  if (!symtab_function_p (lsei_node (lsei))
>>>> +  if (!(lsei_node (lsei)->is_function ())
>>>>        || !lto_symtab_encoder_in_partition_p (encoder, lsei_node
>>>> (lsei)))
>>>>      lsei_next_function_in_partition (&lsei);
>>>>
>>>> @@ -1146,7 +1146,7 @@ lsei_next_variable_in_partition (lto_sym
>>>>  {
>>>>    lsei_next (lsei);
>>>>    while (!lsei_end_p (*lsei)
>>>> -     && (!symtab_variable_p (lsei_node (*lsei))
>>>> +     && (!lsei_node (*lsei)->is_variable ()
>>>>           || !lto_symtab_encoder_in_partition_p (lsei->encoder,
>>>> lsei_node
>>>> (*lsei))))
>>>>      lsei_next (lsei);
>>>>  }
>>>> @@ -1159,7 +1159,7 @@ lsei_start_variable_in_partition (lto_sy
>>>>
>>>>    if (lsei_end_p (lsei))
>>>>      return lsei;
>>>> -  if (!symtab_variable_p (lsei_node (lsei))
>>>> +  if (!lsei_node (lsei)->is_variable ()
>>>>        || !lto_symtab_encoder_in_partition_p (encoder, lsei_node
>>>> (lsei)))
>>>>      lsei_next_variable_in_partition (&lsei);
>>>>
>>>>
>>>> --
>>>> Lawrence Crowl
>>>
>>
>>
>> --
>> Lawrence Crowl
>
Diego Novillo Oct. 4, 2012, 6:16 p.m. UTC | #5
On Thu, Oct 4, 2012 at 2:14 PM, Lawrence Crowl <crowl@googlers.com> wrote:

> So, Jan Hubicka requested and approved the current spelling.
> What now?

I don't think we should hold this up.  The names Jan requested seem
reasonable enough.  We seem to be running in circles here.


Diego.
Richard Biener Oct. 5, 2012, 8:49 a.m. UTC | #6
On Thu, Oct 4, 2012 at 8:16 PM, Diego Novillo <dnovillo@google.com> wrote:
> On Thu, Oct 4, 2012 at 2:14 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>
>> So, Jan Hubicka requested and approved the current spelling.
>> What now?
>
> I don't think we should hold this up.  The names Jan requested seem
> reasonable enough.  We seem to be running in circles here.

I suppose I have your promise that we'll release with consistent names.
Please allocate some work hours on your side for the renaming of
cgraph_node and varpool_node for the case Honza doesn't get to it in time.

I see all these patches with mixed feeling - it puts breaks on all developers
because they need to learn the new interface which does not bring any
immediate benefit.  So I think _your_ development time would be better
spent by fixing open bugs or by tackling some of the existing scalability
issues in GCC (rather than quoting funny '0.001% faster with 99% confidence'
stuff).

Thanks,
Richard.

>
> Diego.
Jan Hubicka Oct. 5, 2012, 9:52 a.m. UTC | #7
> On Thu, Oct 4, 2012 at 8:16 PM, Diego Novillo <dnovillo@google.com> wrote:
> > On Thu, Oct 4, 2012 at 2:14 PM, Lawrence Crowl <crowl@googlers.com> wrote:
> >
> >> So, Jan Hubicka requested and approved the current spelling.
> >> What now?
> >
> > I don't think we should hold this up.  The names Jan requested seem
> > reasonable enough.  We seem to be running in circles here.
> 
> I suppose I have your promise that we'll release with consistent names.
> Please allocate some work hours on your side for the renaming of
> cgraph_node and varpool_node for the case Honza doesn't get to it in time.

Not that I would not agree with Richard with most of his points.  To be however
fair here, I only asked to continue naming I already introduced in:

/* Return true when NODE is function.  */
static inline bool
symtab_function_p (symtab_node node)
{
  return node->symbol.type == SYMTAB_FUNCTION;
}

/* Return true when NODE is variable.  */
static inline bool
symtab_variable_p (symtab_node node)
{
  return node->symbol.type == SYMTAB_VARIABLE;
}

Even if variable are represented by varpool and functions by cgraph, I do not
see these names more confusing compared to symtab_cgraph_p/symtab_varpool_p.
The most common use is when you walk the symbol table and you want to handle
functions and variables specially.

The new interface with try_ scheme gives a bit more inconsistent feeling,
but it is just an surface, nothing really changes.

I am not happy with current naming scheme and also with the fact that for
gengtype reasons we also have symtab_node typedef, but for varpool and cgraph
we use struct (this is because symtab_node has to be union without GTY
supporting inheritance).

Introducing symtab I did not have much other options and I expected that
at the end of this stage1 I will clean it up.  This is, well, more or less now
when assuming that there are no major patches to this area just to appear
for this stage1.

I guess we all agreed we want to drop cgraph/varpool nodes in favor of
functions/ variables.  How realistic is for gengtype to support inheritance
this release cycle?  I would really like to see these three turned into classes
with the inheritance this release cycle.  Renaming them during the process
should be easy and just a nice bonus.

Honza
Nathan Froyd Oct. 5, 2012, 10:50 a.m. UTC | #8
----- Original Message -----
> I see all these patches with mixed feeling - it puts breaks on all
> developers
> because they need to learn the new interface which does not bring any
> immediate benefit.  So I think _your_ development time would be
> better
> spent by fixing open bugs or by tackling some of the existing
> scalability
> issues in GCC (rather than quoting funny '0.001% faster with 99%
> confidence'
> stuff).

This tone is unnecessary.

I, for one, think that it's excellent that Lawrence is writing these
cleanup patches and measuring what impact they have on performance.
Bonus points that they are making the compiler faster.  Speed of the 
compiler *is* a scalability issue, and it's one that GCC doesn't
appear to have paid all that much attention to over the years.

-Nathan
Richard Biener Oct. 5, 2012, 11:05 a.m. UTC | #9
On Fri, Oct 5, 2012 at 12:50 PM, Nathan Froyd <froydnj@mozilla.com> wrote:
> ----- Original Message -----
>> I see all these patches with mixed feeling - it puts breaks on all
>> developers
>> because they need to learn the new interface which does not bring any
>> immediate benefit.  So I think _your_ development time would be
>> better
>> spent by fixing open bugs or by tackling some of the existing
>> scalability
>> issues in GCC (rather than quoting funny '0.001% faster with 99%
>> confidence'
>> stuff).
>
> This tone is unnecessary.

Sorry, that wasn't intended.  I question these numbers because
unless you bootstrap say 100 times the noise in bootstrap speed
is way too high to make such claims.  Of course critical information
is missing:

"The new code bootstraps .616% faster with a 99% confidence of being faster."

99% confidence on what basis?  What's your sample size?

Why does the patch need this kind of "marketing"?

> I, for one, think that it's excellent that Lawrence is writing these
> cleanup patches and measuring what impact they have on performance.
> Bonus points that they are making the compiler faster.  Speed of the
> compiler *is* a scalability issue, and it's one that GCC doesn't
> appear to have paid all that much attention to over the years.

I just don't believe the 0.5% numbers.

Richard.

> -Nathan
Diego Novillo Oct. 5, 2012, 12:43 p.m. UTC | #10
On Fri, Oct 5, 2012 at 7:05 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:

> Sorry, that wasn't intended.  I question these numbers because
> unless you bootstrap say 100 times the noise in bootstrap speed
> is way too high to make such claims.  Of course critical information
> is missing:

I agree with Nathan.  Your tone is sometimes borderline insulting.  It
creates unnecessary friction and does not serve anybody's purpose.
There is no need to be so antagonistic at all times.

> "The new code bootstraps .616% faster with a 99% confidence of being faster."
>
> 99% confidence on what basis?  What's your sample size?

Perhaps Lawrence can explain a bit more how he's getting these
numbers.  But they are not pulled out of thin air and he does go to
the extra effort of measuring them and computing the differences.

> Why does the patch need this kind of "marketing"?

Because (a) we have always said that we want to make sure that the C++
conversion provides useful benefits, and (b) there has been so much
negative pressure on our work, that we sometimes try to find some
benefit when reality may provide neutral results.

>> I, for one, think that it's excellent that Lawrence is writing these
>> cleanup patches and measuring what impact they have on performance.
>> Bonus points that they are making the compiler faster.  Speed of the
>> compiler *is* a scalability issue, and it's one that GCC doesn't
>> appear to have paid all that much attention to over the years.
>
> I just don't believe the 0.5% numbers.

Then ask.  Don't mock, please.


Diego.
Steven Bosscher Oct. 5, 2012, 1:58 p.m. UTC | #11
On Fri, Oct 5, 2012 at 2:43 PM, Diego Novillo wrote:
> Because (...) there has been so much
> negative pressure on our work, that we sometimes try to find some
> benefit when reality may provide neutral results.

When people say "your work sucks", they probably don't mean to apply
negative pressure but just that there is a strong pulling force in
your direction ;-)

Ciao!
Steven
Steven Bosscher Oct. 5, 2012, 2:06 p.m. UTC | #12
On Fri, Oct 5, 2012 at 2:43 PM, Diego Novillo wrote:
> Because (...) there has been so much
> negative pressure on our work, that we sometimes try to find some
> benefit when reality may provide neutral results.

When people say "your work sucks", they probably don't mean to apply
negative pressure but just that there is a strong pulling force in
your direction ;-)

Ciao!
Steven
Lawrence Crowl Oct. 5, 2012, 9:50 p.m. UTC | #13
On 10/5/12, Diego Novillo <dnovillo@google.com> wrote:
> On Oct 5, 2012 Richard Guenther <richard.guenther@gmail.com> wrote:
> > Sorry, that wasn't intended.  I question these numbers because
> > unless you bootstrap say 100 times the noise in bootstrap
> > speed is way too high to make such claims.  Of course critical
> > information is missing:
>
> I agree with Nathan.  Your tone is sometimes borderline insulting.
> It creates unnecessary friction and does not serve anybody's
> purpose.  There is no need to be so antagonistic at all times.
>
> > "The new code bootstraps .616% faster with a 99% confidence of
> > being faster."
> >
> > 99% confidence on what basis?  What's your sample size?
>
> Perhaps Lawrence can explain a bit more how he's getting these
> numbers.  But they are not pulled out of thin air and he does go to
> the extra effort of measuring them and computing the differences.

The intent of the work is to compare the performance of the
unmodified compiler and the compiler with my patch.

For each compiler, I run the third stage of the boot with
-ftime-report ten times.  By running the third stage, I test
two things.  Stage two has all the benefits of any performance
improvements that the restructuring can deliver to end users.
But since it is compiling stage three, it is also accounting for
any increased time that the new C++ code takes in the bootstrap.
The end customer won't pay that cost, but it was a concern among
GCC developers.

By parsing the log files, I extract total CPU time for each run.
So, I have two samples, each with ten data points.  Each sample
has a sampled mean and a variance, from which you can compute
a confidence interval, in which the true mean is likely to be.
You can then compare the two confidence intervals to determine
the likely hood that one is better or worse than the other.  So,
in the statement "The new code bootstraps .616% faster with a 99%
confidence of being faster", the last phrase says if we were to
run that same experiment 100 times, we might get one case where
the compiler was slower.

For most purposes, a 95% confidence is sufficient for medical
interventions.  Compile-time isn't that important, so we could
easily get by on 70% confidence.

In any event, the sample size is only relevant to the extent
that larger sample sizes yield more confidence.  More consistent
runs also yield more confidence.  Algorithmic changes, which would
yield larger difference, would also yield more confidence.  Since I
report the confidence, you don't need to worry about sample size
or isolation from system contention, etc.  All those issues would
have affected confidence.

> > Why does the patch need this kind of "marketing"?
>
> Because (a) we have always said that we want to make sure that
> the C++ conversion provides useful benefits, and (b) there has
> been so much negative pressure on our work, that we sometimes
> try to find some benefit when reality may provide neutral results.

Yes, in particular, there was some concern that the cost of compiling
the templates used in the hash tables would increase the bootstrap
time significantly.  In these cases, I have shown that the benefit
of using them exceeds the cost of compiling them.

If no one cares about these time reports, then I will gladly stop
spending the effort to make them.

> > > I, for one, think that it's excellent that Lawrence is
> > > writing these cleanup patches and measuring what impact they
> > > have on performance.  Bonus points that they are making the
> > > compiler faster.  Speed of the compiler *is* a scalability
> > > issue, and it's one that GCC doesn't appear to have paid all
> > > that much attention to over the years.
> >
> > I just don't believe the 0.5% numbers.
>
> Then ask.  Don't mock, please.
Steven Bosscher Oct. 5, 2012, 10:04 p.m. UTC | #14
On Fri, Oct 5, 2012 at 11:50 PM, Lawrence Crowl <crowl@googlers.com> wrote:
> If no one cares about these time reports, then I will gladly stop
> spending the effort to make them.

It's not that no-one cases, I think, but the mathematics don't have to
be so complicated. Just showing or saying there's no significant
compile time impact is quite enough.

As for the confidence level, it depends so much on what else your
machine is doing (other users, kernel, whatever) that statistics
become just that: statistics, those worse-than-damned-lies numbers :-)

FWIW: I usually do 3 runs on a set of pre-processed cc1-i files
(excluding very small files, but also including a few non-cc1 files
e.g. interpret.cc from libjava) with patched and unpatched compiler,
and declare victory if there's no difference greater than a few % on
any of the test files.

Ciao!
Steven
Lawrence Crowl Oct. 10, 2012, 12:03 a.m. UTC | #15
On 10/5/12, Jan Hubicka <hubicka@ucw.cz> wrote:
>> On Thu, Oct 4, 2012 at 8:16 PM, Diego Novillo <dnovillo@google.com> wrote:
>> > On Thu, Oct 4, 2012 at 2:14 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>> >
>> >> So, Jan Hubicka requested and approved the current spelling.
>> >> What now?
>> >
>> > I don't think we should hold this up.  The names Jan requested seem
>> > reasonable enough.  We seem to be running in circles here.
>>
>> I suppose I have your promise that we'll release with consistent names.
>> Please allocate some work hours on your side for the renaming of
>> cgraph_node and varpool_node for the case Honza doesn't get to it in
>> time.
>
> Not that I would not agree with Richard with most of his points.  To be
> however
> fair here, I only asked to continue naming I already introduced in:
>
> /* Return true when NODE is function.  */
> static inline bool
> symtab_function_p (symtab_node node)
> {
>   return node->symbol.type == SYMTAB_FUNCTION;
> }
>
> /* Return true when NODE is variable.  */
> static inline bool
> symtab_variable_p (symtab_node node)
> {
>   return node->symbol.type == SYMTAB_VARIABLE;
> }
>
> Even if variable are represented by varpool and functions by cgraph, I do
> not
> see these names more confusing compared to
> symtab_cgraph_p/symtab_varpool_p.
> The most common use is when you walk the symbol table and you want to
> handle
> functions and variables specially.
>
> The new interface with try_ scheme gives a bit more inconsistent feeling,
> but it is just an surface, nothing really changes.
>
> I am not happy with current naming scheme and also with the fact that for
> gengtype reasons we also have symtab_node typedef, but for varpool and
> cgraph
> we use struct (this is because symtab_node has to be union without GTY
> supporting inheritance).
>
> Introducing symtab I did not have much other options and I expected that
> at the end of this stage1 I will clean it up.  This is, well, more or less
> now
> when assuming that there are no major patches to this area just to appear
> for this stage1.
>
> I guess we all agreed we want to drop cgraph/varpool nodes in favor of
> functions/ variables.  How realistic is for gengtype to support inheritance
> this release cycle?  I would really like to see these three turned into
> classes
> with the inheritance this release cycle.  Renaming them during the process
> should be easy and just a nice bonus.

I would like some clarity.  Can I commit this patch?
Diego Novillo Oct. 10, 2012, 11:37 p.m. UTC | #16
On Tue, Oct 9, 2012 at 8:03 PM, Lawrence Crowl <crowl@googlers.com> wrote:

> I would like some clarity.  Can I commit this patch?

I'm thinking, yes.  I will be making the gengtype changes in time for
stage 1, so further renames can continue after those patches are in.

Jan, Richard?  Any strong objections?


Diego.
Xinliang David Li Oct. 11, 2012, 5:31 a.m. UTC | #17
On Fri, Oct 5, 2012 at 1:49 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Thu, Oct 4, 2012 at 8:16 PM, Diego Novillo <dnovillo@google.com> wrote:
>> On Thu, Oct 4, 2012 at 2:14 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>>
>>> So, Jan Hubicka requested and approved the current spelling.
>>> What now?
>>
>> I don't think we should hold this up.  The names Jan requested seem
>> reasonable enough.  We seem to be running in circles here.
>
> I suppose I have your promise that we'll release with consistent names.
> Please allocate some work hours on your side for the renaming of
> cgraph_node and varpool_node for the case Honza doesn't get to it in time.
>
> I see all these patches with mixed feeling - it puts breaks on all developers
> because they need to learn the new interface which does not bring any
> immediate benefit.  So I think _your_ development time would be better
> spent by fixing open bugs or by tackling some of the existing scalability
> issues in GCC (rather than quoting funny '0.001% faster with 99% confidence'
> stuff).
>

Interface cleanup will help GCC in the long run assuming it is done
correctly. There will be short term churns for sure. However I think
it is also important to get things right in as few steps as possible
with a better/more carefully thought design.

David

> Thanks,
> Richard.
>
>>
>> Diego.
Richard Biener Oct. 11, 2012, 1:09 p.m. UTC | #18
On Thu, Oct 11, 2012 at 7:31 AM, Xinliang David Li <davidxl@google.com> wrote:
> On Fri, Oct 5, 2012 at 1:49 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Thu, Oct 4, 2012 at 8:16 PM, Diego Novillo <dnovillo@google.com> wrote:
>>> On Thu, Oct 4, 2012 at 2:14 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>>>
>>>> So, Jan Hubicka requested and approved the current spelling.
>>>> What now?
>>>
>>> I don't think we should hold this up.  The names Jan requested seem
>>> reasonable enough.  We seem to be running in circles here.
>>
>> I suppose I have your promise that we'll release with consistent names.
>> Please allocate some work hours on your side for the renaming of
>> cgraph_node and varpool_node for the case Honza doesn't get to it in time.
>>
>> I see all these patches with mixed feeling - it puts breaks on all developers
>> because they need to learn the new interface which does not bring any
>> immediate benefit.  So I think _your_ development time would be better
>> spent by fixing open bugs or by tackling some of the existing scalability
>> issues in GCC (rather than quoting funny '0.001% faster with 99% confidence'
>> stuff).
>>
>
> Interface cleanup will help GCC in the long run assuming it is done
> correctly. There will be short term churns for sure. However I think
> it is also important to get things right in as few steps as possible
> with a better/more carefully thought design.

I agree.

There is no reason to change things just to change them.

Richard.

> David
>
>> Thanks,
>> Richard.
>>
>>>
>>> Diego.
diff mbox

Patch

Index: gcc/ChangeLog

2012-10-02  Lawrence Crowl  <crowl@google.com

	* cgraph.h (varpool_node): Rename to varpool_node_for_decl.
	Adjust callers to match.
	(symtab_node_def::try_function): New.
	Change most calls to symtab_function_p with calls to
	symtab_node_def::try_function.
	(symtab_node_def::try_variable): New.
	Change most calls to symtab_variable_p with calls to
	symtab_node_def::try_variable.
	(symtab_function_p): Rename to symtab_node_def::is_function.
	Adjust remaining callers to match.
	(symtab_variable_p): Rename to symtab_node_def::is_variable.
	Adjust remaining callers to match.
	* cgraph.c (cgraph_node_for_asm): Remove redundant call to
	symtab_node_for_asm.
	* cgraphunit.c (symbol_finalized_and_needed): New.
	(symbol_finalized): New.
	(cgraph_analyze_functions): Split complicated conditionals out into
	above new functions.


Index: gcc/lto-symtab.c
===================================================================
--- gcc/lto-symtab.c	(revision 192010)
+++ gcc/lto-symtab.c	(working copy)
@@ -566,11 +566,11 @@  lto_symtab_merge_cgraph_nodes_1 (symtab_

       if (!symtab_real_symbol_p (e))
 	continue;
-      if (symtab_function_p (e)
-	  && !DECL_BUILT_IN (e->symbol.decl))
-	lto_cgraph_replace_node (cgraph (e), cgraph (prevailing));
-      if (symtab_variable_p (e))
-	lto_varpool_replace_node (varpool (e), varpool (prevailing));
+      cgraph_node *ce = e->try_function ();
+      if (ce && !DECL_BUILT_IN (e->symbol.decl))
+	lto_cgraph_replace_node (ce, cgraph (prevailing));
+      if (varpool_node *ve = e->try_variable ())
+	lto_varpool_replace_node (ve, varpool (prevailing));
     }

   return;
Index: gcc/cgraphbuild.c
===================================================================
--- gcc/cgraphbuild.c	(revision 192010)
+++ gcc/cgraphbuild.c	(working copy)
@@ -84,7 +84,7 @@  record_reference (tree *tp, int *walk_su

       if (TREE_CODE (decl) == VAR_DECL)
 	{
-	  struct varpool_node *vnode = varpool_node (decl);
+	  struct varpool_node *vnode = varpool_node_for_decl (decl);
 	  ipa_record_reference ((symtab_node)ctx->varpool_node,
 				(symtab_node)vnode,
 				IPA_REF_ADDR, NULL);
@@ -123,7 +123,7 @@  record_type_list (struct cgraph_node *no
 	  type = TREE_OPERAND (type, 0);
 	  if (TREE_CODE (type) == VAR_DECL)
 	    {
-	      struct varpool_node *vnode = varpool_node (type);
+	      struct varpool_node *vnode = varpool_node_for_decl (type);
 	      ipa_record_reference ((symtab_node)node,
 				    (symtab_node)vnode,
 				    IPA_REF_ADDR, NULL);
@@ -233,7 +233,7 @@  mark_address (gimple stmt, tree addr, vo
   else if (addr && TREE_CODE (addr) == VAR_DECL
 	   && (TREE_STATIC (addr) || DECL_EXTERNAL (addr)))
     {
-      struct varpool_node *vnode = varpool_node (addr);
+      struct varpool_node *vnode = varpool_node_for_decl (addr);

       ipa_record_reference ((symtab_node)data,
 			    (symtab_node)vnode,
@@ -262,7 +262,7 @@  mark_load (gimple stmt, tree t, void *da
   else if (t && TREE_CODE (t) == VAR_DECL
 	   && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
     {
-      struct varpool_node *vnode = varpool_node (t);
+      struct varpool_node *vnode = varpool_node_for_decl (t);

       ipa_record_reference ((symtab_node)data,
 			    (symtab_node)vnode,
@@ -280,7 +280,7 @@  mark_store (gimple stmt, tree t, void *d
   if (t && TREE_CODE (t) == VAR_DECL
       && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
     {
-      struct varpool_node *vnode = varpool_node (t);
+      struct varpool_node *vnode = varpool_node_for_decl (t);

       ipa_record_reference ((symtab_node)data,
 			    (symtab_node)vnode,
@@ -392,7 +392,7 @@  void
 record_references_in_initializer (tree decl, bool only_vars)
 {
   struct pointer_set_t *visited_nodes = pointer_set_create ();
-  struct varpool_node *node = varpool_node (decl);
+  struct varpool_node *node = varpool_node_for_decl (decl);
   struct record_reference_ctx ctx = {false, NULL};

   ctx.varpool_node = node;
Index: gcc/cgraph.c
===================================================================
--- gcc/cgraph.c	(revision 192010)
+++ gcc/cgraph.c	(working copy)
@@ -503,12 +503,15 @@  cgraph_add_thunk (struct cgraph_node *de
 struct cgraph_node *
 cgraph_node_for_asm (tree asmname)
 {
-  symtab_node node = symtab_node_for_asm (asmname);
-
   /* We do not want to look at inline clones.  */
-  for (node = symtab_node_for_asm (asmname); node; node =
node->symbol.next_sharing_asm_name)
-    if (symtab_function_p (node) && !cgraph(node)->global.inlined_to)
-      return cgraph (node);
+  for (symtab_node node = symtab_node_for_asm (asmname);
+       node;
+       node = node->symbol.next_sharing_asm_name)
+    {
+      cgraph_node *cn = node->try_function ();
+      if (cn && !cn->global.inlined_to)
+	return cn;
+    }
   return NULL;
 }

Index: gcc/cgraph.h
===================================================================
--- gcc/cgraph.h	(revision 192010)
+++ gcc/cgraph.h	(working copy)
@@ -456,13 +456,56 @@  struct GTY(()) asm_node {
 /* Symbol table entry.  */
 union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"),
 	   chain_prev ("%h.symbol.previous"))) symtab_node_def {
+  /* Dynamic type testers. */
+  bool GTY((skip)) is_function ();
+  bool GTY((skip)) is_variable ();
+  /* Conditional accessors return null if not the requested type.  */
+  cgraph_node * GTY((skip)) try_function ();
+  varpool_node * GTY((skip)) try_variable ();
+
   struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol;
-  /* Use cgraph (symbol) accessor to get cgraph_node.  */
+  /* To access the following fields,
+     use the conditional accessors try_function and try_variable above
+     or the asserting accessor functions cgraph and varpool.  */
   struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function;
-  /* Use varpool (symbol) accessor to get varpool_node.  */
   struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable;
 };

+/* Report whether or not THIS symtab node is a function, aka cgraph_node.  */
+
+inline bool
+symtab_node_def::is_function ()
+{
+  return symbol.type == SYMTAB_FUNCTION;
+}
+
+/* Report whether or not THIS symtab node is a vriable, aka varpool_node.  */
+
+inline bool
+symtab_node_def::is_variable ()
+{
+  return symbol.type == SYMTAB_VARIABLE;
+}
+
+/* If THIS symtab node is a function, return a pointer to the cgraph_node,
+   otherwise return NULL.  */
+
+inline cgraph_node *
+symtab_node_def::try_function ()
+{
+  return is_function () ? &x_function : NULL;
+}
+
+/* If THIS symtab node is a variable, return a pointer to the varpool_node,
+   otherwise return NULL.  */
+
+inline varpool_node *
+symtab_node_def::try_variable()
+{
+  return is_variable () ? &x_variable : NULL;
+}
+
+
 extern GTY(()) symtab_node symtab_nodes;
 extern GTY(()) int cgraph_n_nodes;
 extern GTY(()) int cgraph_max_uid;
@@ -685,7 +728,7 @@  bool cgraph_maybe_hot_edge_p (struct cgr
 bool cgraph_optimize_for_size_p (struct cgraph_node *);

 /* In varpool.c  */
-struct varpool_node *varpool_node (tree);
+struct varpool_node *varpool_node_for_decl (tree);
 struct varpool_node *varpool_node_for_asm (tree asmname);
 void varpool_mark_needed_node (struct varpool_node *);
 void debug_varpool (void);
@@ -715,19 +758,6 @@  void varpool_add_new_variable (tree);
 void symtab_initialize_asm_name_hash (void);
 void symtab_prevail_in_asm_name_hash (symtab_node node);

-/* Return true when NODE is function.  */
-static inline bool
-symtab_function_p (symtab_node node)
-{
-  return node->symbol.type == SYMTAB_FUNCTION;
-}
-
-/* Return true when NODE is variable.  */
-static inline bool
-symtab_variable_p (symtab_node node)
-{
-  return node->symbol.type == SYMTAB_VARIABLE;
-}

 /* Return callgraph node for given symbol and check it is a function. */
 static inline struct cgraph_node *
@@ -800,10 +830,8 @@  varpool_first_variable (void)
 {
   symtab_node node;
   for (node = symtab_nodes; node; node = node->symbol.next)
-    {
-      if (symtab_variable_p (node))
-	return varpool (node);
-    }
+    if (varpool_node *vnode = node->try_variable ())
+      return vnode;
   return NULL;
 }

@@ -813,10 +841,8 @@  varpool_next_variable (struct varpool_no
 {
   symtab_node node1 = (symtab_node) node->symbol.next;
   for (; node1; node1 = node1->symbol.next)
-    {
-      if (symtab_variable_p (node1))
-	return varpool (node1);
-    }
+    if (varpool_node *vnode1 = node1->try_variable ())
+      return vnode1;
   return NULL;
 }
 /* Walk all variables.  */
@@ -832,9 +858,9 @@  varpool_first_static_initializer (void)
   symtab_node node;
   for (node = symtab_nodes; node; node = node->symbol.next)
     {
-      if (symtab_variable_p (node)
-	  && DECL_INITIAL (node->symbol.decl))
-	return varpool (node);
+      varpool_node *vnode = node->try_variable ();
+      if (vnode && DECL_INITIAL (node->symbol.decl))
+	return vnode;
     }
   return NULL;
 }
@@ -846,9 +872,9 @@  varpool_next_static_initializer (struct
   symtab_node node1 = (symtab_node) node->symbol.next;
   for (; node1; node1 = node1->symbol.next)
     {
-      if (symtab_variable_p (node1)
-	  && DECL_INITIAL (node1->symbol.decl))
-	return varpool (node1);
+      varpool_node *vnode1 = node1->try_variable ();
+      if (vnode1 && DECL_INITIAL (node1->symbol.decl))
+	return vnode1;
     }
   return NULL;
 }
@@ -865,8 +891,9 @@  varpool_first_defined_variable (void)
   symtab_node node;
   for (node = symtab_nodes; node; node = node->symbol.next)
     {
-      if (symtab_variable_p (node) && varpool (node)->analyzed)
-	return varpool (node);
+      varpool_node *vnode = node->try_variable ();
+      if (vnode && vnode->analyzed)
+	return vnode;
     }
   return NULL;
 }
@@ -878,8 +905,9 @@  varpool_next_defined_variable (struct va
   symtab_node node1 = (symtab_node) node->symbol.next;
   for (; node1; node1 = node1->symbol.next)
     {
-      if (symtab_variable_p (node1) && varpool (node1)->analyzed)
-	return varpool (node1);
+      varpool_node *vnode1 = node1->try_variable ();
+      if (vnode1 && vnode1->analyzed)
+	return vnode1;
     }
   return NULL;
 }
@@ -895,8 +923,9 @@  cgraph_first_defined_function (void)
   symtab_node node;
   for (node = symtab_nodes; node; node = node->symbol.next)
     {
-      if (symtab_function_p (node) && cgraph (node)->analyzed)
-	return cgraph (node);
+      cgraph_node *cn = node->try_function ();
+      if (cn && cn->analyzed)
+	return cn;
     }
   return NULL;
 }
@@ -908,8 +937,9 @@  cgraph_next_defined_function (struct cgr
   symtab_node node1 = (symtab_node) node->symbol.next;
   for (; node1; node1 = node1->symbol.next)
     {
-      if (symtab_function_p (node1) && cgraph (node1)->analyzed)
-	return cgraph (node1);
+      cgraph_node *cn1 = node1->try_function ();
+      if (cn1 && cn1->analyzed)
+	return cn1;
     }
   return NULL;
 }
@@ -925,10 +955,8 @@  cgraph_first_function (void)
 {
   symtab_node node;
   for (node = symtab_nodes; node; node = node->symbol.next)
-    {
-      if (symtab_function_p (node))
-	return cgraph (node);
-    }
+    if (cgraph_node *cn = node->try_function ())
+      return cn;
   return NULL;
 }

@@ -938,10 +966,8 @@  cgraph_next_function (struct cgraph_node
 {
   symtab_node node1 = (symtab_node) node->symbol.next;
   for (; node1; node1 = node1->symbol.next)
-    {
-      if (symtab_function_p (node1))
-	return cgraph (node1);
-    }
+    if (cgraph_node *cn1 = node1->try_function ())
+      return cn1;
   return NULL;
 }
 /* Walk all functions.  */
@@ -968,9 +994,9 @@  cgraph_first_function_with_gimple_body (
   symtab_node node;
   for (node = symtab_nodes; node; node = node->symbol.next)
     {
-      if (symtab_function_p (node)
-	  && cgraph_function_with_gimple_body_p (cgraph (node)))
-	return cgraph (node);
+      cgraph_node *cn = node->try_function ();
+      if (cn && cgraph_function_with_gimple_body_p (cn))
+	return cn;
     }
   return NULL;
 }
@@ -982,9 +1008,9 @@  cgraph_next_function_with_gimple_body (s
   symtab_node node1 = node->symbol.next;
   for (; node1; node1 = node1->symbol.next)
     {
-      if (symtab_function_p (node1)
-	  && cgraph_function_with_gimple_body_p (cgraph (node1)))
-	return cgraph (node1);
+      cgraph_node *cn1 = node1->try_function ();
+      if (cn1 && cgraph_function_with_gimple_body_p (cn1))
+	return cn1;
     }
   return NULL;
 }
@@ -1183,7 +1209,7 @@  cgraph_alias_aliased_node (struct cgraph

   ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
   gcc_checking_assert (ref->use == IPA_REF_ALIAS);
-  if (symtab_function_p (ref->referred))
+  if (ref->referred->is_function ())
     return ipa_ref_node (ref);
   return NULL;
 }
@@ -1197,7 +1223,7 @@  varpool_alias_aliased_node (struct varpo

   ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
   gcc_checking_assert (ref->use == IPA_REF_ALIAS);
-  if (symtab_variable_p (ref->referred))
+  if (ref->referred->is_variable ())
     return ipa_ref_varpool_node (ref);
   return NULL;
 }
@@ -1328,7 +1354,7 @@  symtab_real_symbol_p (symtab_node node)
   struct cgraph_node *cnode;
   struct ipa_ref *ref;

-  if (!symtab_function_p (node))
+  if (!node->is_function ())
     return true;
   cnode = cgraph (node);
   if (cnode->global.inlined_to)
Index: gcc/tree-emutls.c
===================================================================
--- gcc/tree-emutls.c	(revision 192010)
+++ gcc/tree-emutls.c	(working copy)
@@ -260,7 +260,7 @@  get_emutls_init_templ_addr (tree decl)
   /* Create varpool node for the new variable and finalize it if it is
      not external one.  */
   if (DECL_EXTERNAL (to))
-    varpool_node (to);
+    varpool_node_for_decl (to);
   else
     varpool_add_new_variable (to);
   return build_fold_addr_expr (to);
@@ -332,7 +332,7 @@  new_emutls_decl (tree decl, tree alias_o
   /* Create varpool node for the new variable and finalize it if it is
      not external one.  */
   if (DECL_EXTERNAL (to))
-    varpool_node (to);
+    varpool_node_for_decl (to);
   else if (!alias_of)
     varpool_add_new_variable (to);
   else
Index: gcc/ipa-reference.c
===================================================================
--- gcc/ipa-reference.c	(revision 192010)
+++ gcc/ipa-reference.c	(working copy)
@@ -482,7 +482,7 @@  analyze_function (struct cgraph_node *fn
   local = init_function_info (fn);
   for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list,
i, ref); i++)
     {
-      if (!symtab_variable_p (ref->referred))
+      if (!ref->referred->is_variable ())
 	continue;
       var = ipa_ref_varpool_node (ref)->symbol.decl;
       if (!is_proper_for_analysis (var))
@@ -979,8 +979,6 @@  stream_out_bitmap (struct lto_simple_out
 static void
 ipa_reference_write_optimization_summary (void)
 {
-  struct cgraph_node *node;
-  symtab_node snode;
   struct lto_simple_output_block *ob
     = lto_create_simple_output_block (LTO_section_ipa_reference);
   unsigned int count = 0;
@@ -994,12 +992,10 @@  ipa_reference_write_optimization_summary
   /* See what variables we are interested in.  */
   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      struct varpool_node *vnode;
-      snode = lto_symtab_encoder_deref (encoder, i);
-      if (!symtab_variable_p (snode))
-	continue;
-      vnode = varpool (snode);
-      if (bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      varpool_node *vnode = snode->try_variable ();
+      if (vnode
+	  && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
 	  && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder))
 	{
 	  tree decl = vnode->symbol.decl;
@@ -1013,10 +1009,12 @@  ipa_reference_write_optimization_summary

   if (ltrans_statics_bitcount)
     for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
-      if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder, i))
-	  && write_node_summary_p (cgraph (snode),
-				   encoder, ltrans_statics))
+      {
+	symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+	cgraph_node *cnode = snode->try_function ();
+	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
 	  count++;
+      }

   streamer_write_uhwi_stream (ob->main_stream, count);
   if (count)
@@ -1027,17 +1025,15 @@  ipa_reference_write_optimization_summary
   if (ltrans_statics_bitcount)
     for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
       {
-	snode = lto_symtab_encoder_deref (encoder, i);
-	if (!symtab_function_p (snode))
-	  continue;
-	node = cgraph (snode);
-	if (write_node_summary_p (node, encoder, ltrans_statics))
+	symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+	cgraph_node *cnode = snode->try_function ();
+	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
 	  {
 	    ipa_reference_optimization_summary_t info;
 	    int node_ref;

-	    info = get_reference_optimization_summary (node);
-	    node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
+	    info = get_reference_optimization_summary (cnode);
+	    node_ref = lto_symtab_encoder_encode (encoder, snode);
 	    streamer_write_uhwi_stream (ob->main_stream, node_ref);

 	    stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
Index: gcc/cgraphunit.c
===================================================================
--- gcc/cgraphunit.c	(revision 192010)
+++ gcc/cgraphunit.c	(working copy)
@@ -386,7 +386,8 @@  referred_to_p (symtab_node node)
   if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
     return true;
   /* For functions check also calls.  */
-  if (symtab_function_p (node) && cgraph (node)->callers)
+  cgraph_node *cn = node->try_function ();
+  if (cn && cn->callers)
     return true;
   return false;
 }
@@ -809,7 +810,7 @@  process_function_and_variable_attributes
 void
 varpool_finalize_decl (tree decl)
 {
-  struct varpool_node *node = varpool_node (decl);
+  struct varpool_node *node = varpool_node_for_decl (decl);

   gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));

@@ -836,6 +837,35 @@  varpool_finalize_decl (tree decl)
     varpool_assemble_decl (node);
 }

+
+/* Determine if a symbol is finalized and needed.  */
+
+inline static bool
+symbol_finalized_and_needed (symtab_node node)
+{
+  if (cgraph_node *cnode = node->try_function ())
+    return cnode->local.finalized
+	   && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl);
+  if (varpool_node *vnode = node->try_variable ())
+    return vnode->finalized
+	   && !DECL_EXTERNAL (vnode->symbol.decl)
+	   && decide_is_variable_needed (vnode, vnode->symbol.decl);
+  return false;
+}
+
+/* Determine if a symbol is finalized.  */
+
+inline static bool
+symbol_finalized (symtab_node node)
+{
+  if (cgraph_node *cnode= node->try_function ())
+    return cnode->local.finalized;
+  if (varpool_node *vnode = node->try_variable ())
+    return vnode->finalized;
+  return false;
+}
+
+
 /* Discover all functions and variables that are trivially needed, analyze
    them as well as all functions and variables referred by them  */

@@ -870,13 +900,7 @@  cgraph_analyze_functions (void)
 	   node != (symtab_node)first_analyzed
 	   && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
 	{
-	  if ((symtab_function_p (node)
-	       && cgraph (node)->local.finalized
-	       && cgraph_decide_is_function_needed (cgraph (node), node->symbol.decl))
-	      || (symtab_variable_p (node)
-		  && varpool (node)->finalized
-		  && !DECL_EXTERNAL (node->symbol.decl)
-		  && decide_is_variable_needed (varpool (node), node->symbol.decl)))
+	  if (symbol_finalized_and_needed (node))
 	    {
 	      enqueue_node (node);
 	      if (!changed && cgraph_dump_file)
@@ -903,18 +927,15 @@  cgraph_analyze_functions (void)
 	  changed = true;
 	  node = first;
 	  first = (symtab_node)first->symbol.aux;
-	  if (symtab_function_p (node) && cgraph (node)->local.finalized)
+	  cgraph_node *cnode = node->try_function ();
+	  if (cnode && cnode->local.finalized)
 	    {
 	      struct cgraph_edge *edge;
-	      struct cgraph_node *cnode;
-	      tree decl;
-
-	      cnode = cgraph (node);
-	      decl = cnode->symbol.decl;
+	      tree decl = cnode->symbol.decl;

-	      /* ??? It is possible to create extern inline function and later using
-		 weak alias attribute to kill its body. See
-		 gcc.c-torture/compile/20011119-1.c  */
+	      /* ??? It is possible to create extern inline function
+	      and later using weak alias attribute to kill its body.
+	      See gcc.c-torture/compile/20011119-1.c  */
 	      if (!DECL_STRUCT_FUNCTION (decl)
 		  && (!cnode->alias || !cnode->thunk.alias)
 		  && !cnode->thunk.thunk_p)
@@ -929,23 +950,25 @@  cgraph_analyze_functions (void)

 	      for (edge = cnode->callees; edge; edge = edge->next_callee)
 		if (edge->callee->local.finalized)
-		  enqueue_node ((symtab_node)edge->callee);
+		   enqueue_node ((symtab_node)edge->callee);

-	      /* 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.  */
+	      /* 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.  */
 	      if (DECL_ABSTRACT_ORIGIN (decl))
 		{
-		  struct cgraph_node *origin_node;
-		  origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
+		  struct cgraph_node *origin_node
+	    	  = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
 		  origin_node->abstract_and_needed = true;
 		}
-
 	    }
-	  else if (symtab_variable_p (node)
-		   && varpool (node)->finalized)
-	    varpool_analyze_node (varpool (node));
+	  else
+	    {
+	      varpool_node *vnode = node->try_variable ();
+	      if (vnode && vnode->finalized)
+		varpool_analyze_node (vnode);
+	    }

 	  if (node->symbol.same_comdat_group)
 	    {
@@ -956,8 +979,7 @@  cgraph_analyze_functions (void)
 		enqueue_node (next);
 	    }
 	  for (i = 0; ipa_ref_list_reference_iterate
(&node->symbol.ref_list, i, ref); i++)
-	    if ((symtab_function_p (ref->referred) && cgraph
(ref->referred)->local.finalized)
-		|| (symtab_variable_p (ref->referred) && varpool (ref->referred)->finalized))
+	    if (symbol_finalized (ref->referred))
 	      enqueue_node (ref->referred);
           cgraph_process_new_functions ();
 	}
@@ -985,10 +1007,9 @@  cgraph_analyze_functions (void)
 	  symtab_remove_node (node);
 	  continue;
 	}
-      if (symtab_function_p (node))
+      if (cgraph_node *cnode = node->try_function ())
 	{
 	  tree decl = node->symbol.decl;
-	  struct cgraph_node *cnode = cgraph (node);

 	  if (cnode->local.finalized && !gimple_has_body_p (decl)
 	      && (!cnode->alias || !cnode->thunk.alias)
@@ -1070,7 +1091,7 @@  handle_alias_pairs (void)
 	}

       if (TREE_CODE (p->decl) == FUNCTION_DECL
-          && target_node && symtab_function_p (target_node))
+          && target_node && target_node->is_function ())
 	{
 	  struct cgraph_node *src_node = cgraph_get_node (p->decl);
 	  if (src_node && src_node->local.finalized)
@@ -1079,7 +1100,7 @@  handle_alias_pairs (void)
 	  VEC_unordered_remove (alias_pair, alias_pairs, i);
 	}
       else if (TREE_CODE (p->decl) == VAR_DECL
-	       && target_node && symtab_variable_p (target_node))
+	       && target_node && target_node->is_variable ())
 	{
 	  varpool_create_variable_alias (p->decl, target_node->symbol.decl);
 	  VEC_unordered_remove (alias_pair, alias_pairs, i);
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 192010)
+++ gcc/cp/decl2.c	(working copy)
@@ -1778,7 +1778,7 @@  import_export_class (tree ctype)
 static bool
 var_finalized_p (tree var)
 {
-  return varpool_node (var)->finalized;
+  return varpool_node_for_decl (var)->finalized;
 }

 /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
@@ -1896,7 +1896,7 @@  maybe_emit_vtables (tree ctype)
 	TREE_ASM_WRITTEN (vtbl) = 1;
       else if (DECL_ONE_ONLY (vtbl))
 	{
-	  current = varpool_node (vtbl);
+	  current = varpool_node_for_decl (vtbl);
 	  if (last)
 	    symtab_add_to_same_comdat_group ((symtab_node) current,
(symtab_node) last);
 	  last = current;
Index: gcc/ipa-ref.c
===================================================================
--- gcc/ipa-ref.c	(revision 192010)
+++ gcc/ipa-ref.c	(working copy)
@@ -42,7 +42,7 @@  ipa_record_reference (symtab_node referr
   struct ipa_ref_list *list, *list2;
   VEC(ipa_ref_t,gc) *old_references;

-  gcc_checking_assert (!stmt || symtab_function_p (referring_node));
+  gcc_checking_assert (!stmt || referring_node->is_function ());
   gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt);

   list = &referring_node->symbol.ref_list;
Index: gcc/lto-cgraph.c
===================================================================
--- gcc/lto-cgraph.c	(revision 192010)
+++ gcc/lto-cgraph.c	(working copy)
@@ -665,7 +665,7 @@  add_references (lto_symtab_encoder_t enc
   int i;
   struct ipa_ref *ref;
   for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
-    if (symtab_function_p (ref->referred))
+    if (ref->referred->is_function ())
       add_node_to (encoder, ipa_ref_node (ref), false);
     else
       lto_symtab_encoder_encode (encoder, ref->referred);
@@ -716,9 +716,8 @@  compute_ltrans_boundary (lto_symtab_enco
   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
       symtab_node node = lto_symtab_encoder_deref (encoder, i);
-      if (symtab_variable_p (node))
+      if (varpool_node *vnode = node->try_variable ())
 	{
-	  struct varpool_node *vnode = varpool (node);
 	  if (DECL_INITIAL (vnode->symbol.decl)
 	      && !lto_symtab_encoder_encode_initializer_p (encoder,
 							   vnode)
@@ -782,8 +781,8 @@  output_symtab (void)
   for (i = 0; i < n_nodes; i++)
     {
       symtab_node node = lto_symtab_encoder_deref (encoder, i);
-      if (symtab_function_p (node))
-        lto_output_node (ob, cgraph (node), encoder);
+      if (cgraph_node *cnode = node->try_function ())
+        lto_output_node (ob, cnode, encoder);
       else
         lto_output_varpool_node (ob, varpool (node), encoder);
 	
@@ -969,7 +968,7 @@  input_varpool_node (struct lto_file_decl
   order = streamer_read_hwi (ib) + order_base;
   decl_index = streamer_read_uhwi (ib);
   var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
-  node = varpool_node (var_decl);
+  node = varpool_node_for_decl (var_decl);
   node->symbol.order = order;
   if (order >= symtab_order)
     symtab_order = order + 1;
@@ -1130,14 +1129,14 @@  input_cgraph_1 (struct lto_file_decl_dat
   /* AUX pointers should be all non-zero for function nodes read from
the stream.  */
 #ifdef ENABLE_CHECKING
   FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
-    gcc_assert (node->symbol.aux || !symtab_function_p (node));
+    gcc_assert (node->symbol.aux || !node->is_function ());
 #endif
   FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
     {
       int ref;
-      if (symtab_function_p (node))
+      if (cgraph_node *cnode = node->try_function ())
 	{
-	  ref = (int) (intptr_t) cgraph (node)->global.inlined_to;
+	  ref = (int) (intptr_t) cnode->global.inlined_to;

 	  /* We share declaration of builtins, so we may read same node twice.  */
 	  if (!node->symbol.aux)
@@ -1146,9 +1145,9 @@  input_cgraph_1 (struct lto_file_decl_dat

 	  /* Fixup inlined_to from reference to pointer.  */
 	  if (ref != LCC_NOT_FOUND)
-	    cgraph (node)->global.inlined_to = cgraph (VEC_index
(symtab_node, nodes, ref));
+	    cnode->global.inlined_to = cgraph (VEC_index (symtab_node, nodes, ref));
 	  else
-	    cgraph (node)->global.inlined_to = NULL;
+	    cnode->global.inlined_to = NULL;
 	}

       ref = (int) (intptr_t) node->symbol.same_comdat_group;
@@ -1160,7 +1159,7 @@  input_cgraph_1 (struct lto_file_decl_dat
 	node->symbol.same_comdat_group = NULL;
     }
   FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
-    node->symbol.aux = symtab_function_p (node) ? (void *)1 : NULL;
+    node->symbol.aux = node->is_function () ? (void *)1 : NULL;
   return nodes;
 }

@@ -1435,7 +1434,6 @@  output_node_opt_summary (struct output_b
 static void
 output_cgraph_opt_summary (void)
 {
-  symtab_node node;
   int i, n_nodes;
   lto_symtab_encoder_t encoder;
   struct output_block *ob = create_output_block (LTO_section_cgraph_opt_sum);
@@ -1445,18 +1443,21 @@  output_cgraph_opt_summary (void)
   encoder = ob->decl_state->symtab_node_encoder;
   n_nodes = lto_symtab_encoder_size (encoder);
   for (i = 0; i < n_nodes; i++)
-    if (symtab_function_p (node = lto_symtab_encoder_deref (encoder, i))
-	&& output_cgraph_opt_summary_p (cgraph (node)))
-      count++;
+    {
+      symtab_node node = lto_symtab_encoder_deref (encoder, i);
+      cgraph_node *cnode = node->try_function ();
+      if (cnode && output_cgraph_opt_summary_p (cnode))
+	count++;
+    }
   streamer_write_uhwi (ob, count);
   for (i = 0; i < n_nodes; i++)
     {
-      node = lto_symtab_encoder_deref (encoder, i);
-      if (symtab_function_p (node)
-	  && output_cgraph_opt_summary_p (cgraph (node)))
+      symtab_node node = lto_symtab_encoder_deref (encoder, i);
+      cgraph_node *cnode = node->try_function ();
+      if (cnode && output_cgraph_opt_summary_p (cnode))
 	{
 	  streamer_write_uhwi (ob, i);
-	  output_node_opt_summary (ob, cgraph (node), encoder);
+	  output_node_opt_summary (ob, cnode, encoder);
 	}
     }
   produce_asm (ob, NULL);
Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c	(revision 192010)
+++ gcc/lto-streamer-out.c	(working copy)
@@ -972,7 +972,6 @@  copy_function (struct cgraph_node *node)
 static void
 lto_output (void)
 {
-  struct cgraph_node *node;
   struct lto_out_decl_state *decl_state;
 #ifdef ENABLE_CHECKING
   bitmap output = lto_bitmap_alloc ();
@@ -988,10 +987,9 @@  lto_output (void)
   for (i = 0; i < n_nodes; i++)
     {
       symtab_node snode = lto_symtab_encoder_deref (encoder, i);
-      if (!symtab_function_p (snode))
-	continue;
-      node = cgraph (snode);
-      if (lto_symtab_encoder_encode_body_p (encoder, node)
+      cgraph_node *node = snode->try_function ();
+      if (node
+	  && lto_symtab_encoder_encode_body_p (encoder, node)
 	  && !node->alias
 	  && !node->thunk.thunk_p)
 	{
@@ -1285,8 +1283,6 @@  produce_symtab (struct output_block *ob)
   struct streamer_tree_cache_d *cache = ob->writer_cache;
   char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
   struct pointer_set_t *seen;
-  struct cgraph_node *node;
-  struct varpool_node *vnode;
   struct lto_output_stream stream;
   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
   int i;
@@ -1302,49 +1298,52 @@  produce_symtab (struct output_block *ob)
      This is done so only to handle duplicated symbols in cgraph.  */
   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      cgraph_node *cnode = snode->try_function ();
+      if (!cnode)
 	continue;
-      node = cgraph (lto_symtab_encoder_deref (encoder, i));
-      if (DECL_EXTERNAL (node->symbol.decl))
+      if (DECL_EXTERNAL (cnode->symbol.decl))
 	continue;
-      if (DECL_COMDAT (node->symbol.decl)
-	  && cgraph_comdat_can_be_unshared_p (node))
+      if (DECL_COMDAT (cnode->symbol.decl)
+	  && cgraph_comdat_can_be_unshared_p (cnode))
 	continue;
-      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
+      if ((cnode->alias && !cnode->thunk.alias) || cnode->global.inlined_to)
 	continue;
-      write_symbol (cache, &stream, node->symbol.decl, seen, false);
+      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
     }
   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i)))
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      cgraph_node *cnode = snode->try_function ();
+      if (!cnode)
 	continue;
-      node = cgraph (lto_symtab_encoder_deref (encoder, i));
-      if (!DECL_EXTERNAL (node->symbol.decl))
+      if (!DECL_EXTERNAL (cnode->symbol.decl))
 	continue;
       /* We keep around unused extern inlines in order to be able to inline
 	 them indirectly or via vtables.  Do not output them to symbol
 	 table: they end up being undefined and just consume space.  */
-      if (!node->symbol.address_taken && !node->callers)
+      if (!cnode->symbol.address_taken && !cnode->callers)
 	continue;
-      if (DECL_COMDAT (node->symbol.decl)
-	  && cgraph_comdat_can_be_unshared_p (node))
+      if (DECL_COMDAT (cnode->symbol.decl)
+	  && cgraph_comdat_can_be_unshared_p (cnode))
 	continue;
-      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
+      if ((cnode->alias && !cnode->thunk.alias) || cnode->global.inlined_to)
 	continue;
-      write_symbol (cache, &stream, node->symbol.decl, seen, false);
+      write_symbol (cache, &stream, cnode->symbol.decl, seen, false);
     }

   /* Write all variables.  */
   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      varpool_node *vnode = snode->try_variable ();
+      if (!vnode)
 	continue;
-      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
       if (DECL_EXTERNAL (vnode->symbol.decl))
 	continue;
       /* COMDAT virtual tables can be unshared.  Do not declare them
-	 in the LTO symbol table to prevent linker from forcing them
-	 into the output. */
+	in the LTO symbol table to prevent linker from forcing them
+	into the output. */
       if (DECL_COMDAT (vnode->symbol.decl)
 	  && !vnode->symbol.force_output
 	  && vnode->finalized
@@ -1356,9 +1355,10 @@  produce_symtab (struct output_block *ob)
     }
   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      varpool_node *vnode = snode->try_variable ();
+      if (!vnode)
 	continue;
-      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
       if (!DECL_EXTERNAL (vnode->symbol.decl))
 	continue;
       if (DECL_COMDAT (vnode->symbol.decl)
Index: gcc/ada/gcc-interface/utils.c
===================================================================
--- gcc/ada/gcc-interface/utils.c	(revision 192010)
+++ gcc/ada/gcc-interface/utils.c	(working copy)
@@ -5582,7 +5582,7 @@  gnat_write_global_declarations (void)
 		      void_type_node);
       TREE_STATIC (dummy_global) = 1;
       TREE_ASM_WRITTEN (dummy_global) = 1;
-      node = varpool_node (dummy_global);
+      node = varpool_node_for_decl (dummy_global);
       node->symbol.force_output = 1;

       while (!VEC_empty (tree, types_used_by_cur_var_decl))
Index: gcc/ipa.c
===================================================================
--- gcc/ipa.c	(revision 192010)
+++ gcc/ipa.c	(working copy)
@@ -84,7 +84,7 @@  process_references (struct ipa_ref_list
   struct ipa_ref *ref;
   for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
     {
-      if (symtab_function_p (ref->referred))
+      if (ref->referred->is_function ())
 	{
 	  struct cgraph_node *node = ipa_ref_node (ref);

@@ -290,10 +290,8 @@  symtab_remove_unreachable_nodes (bool be
 			      before_inlining_p, reachable);
 	}

-      if (symtab_function_p (node))
+      if (cgraph_node *cnode = node->try_function ())
 	{
-	  struct cgraph_node *cnode = cgraph (node);
-
 	  /* Mark the callees reachable unless they are direct calls to extern
  	     inline functions we decided to not inline.  */
 	  if (!in_boundary_p)
@@ -332,18 +330,18 @@  symtab_remove_unreachable_nodes (bool be
 	    }
 	}
       /* When we see constructor of external variable, keep referred
nodes in the
-	 boundary.  This will also hold initializers of the external vars NODE
-	 reffers to.  */
-      if (symtab_variable_p (node)
+	boundary.  This will also hold initializers of the external vars NODE
+	refers to.  */
+      varpool_node *vnode = node->try_variable ();
+      if (vnode
 	  && DECL_EXTERNAL (node->symbol.decl)
-	  && !varpool (node)->alias
+	  && !vnode->alias
 	  && in_boundary_p)
-        {
-	  int i;
+	{
 	  struct ipa_ref *ref;
-	  for (i = 0; ipa_ref_list_reference_iterate
(&node->symbol.ref_list, i, ref); i++)
+	  for (int i = 0; ipa_ref_list_reference_iterate
(&node->symbol.ref_list, i, ref); i++)
 	    enqueue_node (ref->referred, &first, reachable);
-        }
+	}
     }

   /* Remove unreachable functions.   */
@@ -526,7 +524,7 @@  cgraph_address_taken_from_non_vtable_p (
     if (ref->use == IPA_REF_ADDR)
       {
 	struct varpool_node *node;
-	if (symtab_function_p (ref->referring))
+	if (ref->referring->is_function ())
 	  return true;
 	node = ipa_ref_referring_varpool_node (ref);
 	if (!DECL_VIRTUAL_P (node->symbol.decl))
Index: gcc/ipa-inline-analysis.c
===================================================================
--- gcc/ipa-inline-analysis.c	(revision 192010)
+++ gcc/ipa-inline-analysis.c	(working copy)
@@ -3811,22 +3811,25 @@  void
 inline_write_summary (void)
 {
   struct cgraph_node *node;
-  symtab_node snode;
   struct output_block *ob = create_output_block (LTO_section_inline_summary);
   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
   unsigned int count = 0;
   int i;

   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
-    if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder, i))
-	&& cgraph (snode)->analyzed)
-      count++;
+    {
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      cgraph_node *cnode = snode->try_function ();
+      if (cnode && cnode->analyzed)
+	count++;
+    }
   streamer_write_uhwi (ob, count);

   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder, i))
-	  && (node = cgraph (snode))->analyzed)
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      cgraph_node *cnode = snode->try_function ();
+      if (cnode && (node = cnode)->analyzed)
 	{
 	  struct inline_summary *info = inline_summary (node);
 	  struct bitpack_d bp;
@@ -3834,7 +3837,7 @@  inline_write_summary (void)
 	  int i;
 	  size_time_entry *e;
 	  struct condition *c;
-
+
 	  streamer_write_uhwi (ob, lto_symtab_encoder_encode (encoder,
(symtab_node)node));
 	  streamer_write_hwi (ob, info->estimated_self_stack_size);
 	  streamer_write_hwi (ob, info->self_size);
@@ -3853,7 +3856,7 @@  inline_write_summary (void)
 	      bp_pack_value (&bp, c->by_ref, 1);
 	      streamer_write_bitpack (&bp);
 	      if (c->agg_contents)
-		streamer_write_uhwi (ob, c->offset);
+	        streamer_write_uhwi (ob, c->offset);
 	    }
 	  streamer_write_uhwi (ob, VEC_length (size_time_entry, info->entry));
 	  for (i = 0;
Index: gcc/lto/lto.c
===================================================================
--- gcc/lto/lto.c	(revision 192010)
+++ gcc/lto/lto.c	(working copy)
@@ -2620,12 +2620,17 @@  lto_wpa_write_files (void)
 	      if (!lto_symtab_encoder_in_partition_p (part->encoder, node))
 		{
 	          fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name (node));
-		  if (symtab_function_p (node)
-		      && lto_symtab_encoder_encode_body_p (part->encoder, cgraph (node)))
+		  cgraph_node *cnode = node->try_function ();
+		  if (cnode
+		      && lto_symtab_encoder_encode_body_p (part->encoder, cnode))
 		    fprintf (cgraph_dump_file, "(body included)");
-		  else if (symtab_variable_p (node)
-		           && lto_symtab_encoder_encode_initializer_p
(part->encoder, varpool (node)))
-		    fprintf (cgraph_dump_file, "(initializer included)");
+		  else
+		    {
+		      varpool_node *vnode = node->try_variable ();
+		      if (vnode
+			  && lto_symtab_encoder_encode_initializer_p (part->encoder, vnode))
+			fprintf (cgraph_dump_file, "(initializer included)");
+		    }
 		}
 	    }
 	  fprintf (cgraph_dump_file, "\n");
Index: gcc/lto/lto-partition.c
===================================================================
--- gcc/lto/lto-partition.c	(revision 192010)
+++ gcc/lto/lto-partition.c	(working copy)
@@ -55,22 +55,22 @@  get_symbol_class (symtab_node node)
 {
   /* Inline clones are always duplicated.
      This include external delcarations.   */
-  if (symtab_function_p (node)
-      && cgraph (node)->global.inlined_to)
+  cgraph_node *cnode = node->try_function ();
+  if (cnode && cnode->global.inlined_to)
     return SYMBOL_DUPLICATE;

   /* External declarations are external.  */
   if (DECL_EXTERNAL (node->symbol.decl))
     return SYMBOL_EXTERNAL;

-  if (symtab_variable_p (node))
+  if (varpool_node *vnode = node->try_variable ())
     {
       /* Constant pool references use local symbol names that can not
          be promoted global.  We should never put into a constant pool
          objects that can not be duplicated across partitions.  */
       if (DECL_IN_CONSTANT_POOL (node->symbol.decl))
 	return SYMBOL_DUPLICATE;
-      gcc_checking_assert (varpool (node)->analyzed);
+      gcc_checking_assert (vnode->analyzed);
     }
   /* Functions that are cloned may stay in callgraph even if they are unused.
      Handle them as external; compute_ltrans_boundary take care to make
@@ -145,7 +145,7 @@  add_references_to_partition (ltrans_part
     /* References to a readonly variable may be constant foled into its value.
        Recursively look into the initializers of the constant variable and add
        references, too.  */
-    else if (symtab_variable_p (ref->referred)
+    else if (ref->referred->is_variable ()
 	     && const_value_known_p (ref->referred->symbol.decl)
 	     && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
       {
@@ -196,9 +196,8 @@  add_symbol_to_partition_1 (ltrans_partit
     }
   node->symbol.aux = (void *)((size_t)node->symbol.aux + 1);

-  if (symtab_function_p (node))
+  if (cgraph_node *cnode = node->try_function ())
     {
-      struct cgraph_node *cnode = cgraph (node);
       struct cgraph_edge *e;
       part->insns += inline_summary (cnode)->self_size;

@@ -247,15 +246,15 @@  contained_in_symbol (symtab_node node)
   if (lookup_attribute ("weakref",
 			DECL_ATTRIBUTES (node->symbol.decl)))
     return node;
-  if (symtab_function_p (node))
+  if (cgraph_node *cnode = node->try_function ())
     {
-      struct cgraph_node *cnode = cgraph_function_node (cgraph (node), NULL);
+      cnode = cgraph_function_node (cnode, NULL);
       if (cnode->global.inlined_to)
 	cnode = cnode->global.inlined_to;
       return (symtab_node) cnode;
     }
-  else if (symtab_variable_p (node))
-    return (symtab_node) varpool_variable_node (varpool (node), NULL);
+  else if (varpool_node *vnode = node->try_variable ())
+    return (symtab_node) varpool_variable_node (vnode, NULL);
   return node;
 }

@@ -302,8 +301,8 @@  undo_partition (ltrans_partition partiti
 	pointer_set_destroy (partition->initializers_visited);
       partition->initializers_visited = NULL;

-      if (symtab_function_p (node))
-        partition->insns -= inline_summary (cgraph (node))->self_size;
+      if (cgraph_node *cnode = node->try_function ())
+        partition->insns -= inline_summary (cnode)->self_size;
       lto_symtab_encoder_delete_node (partition->encoder, node);
       node->symbol.aux = (void *)((size_t)node->symbol.aux - 1);
     }
@@ -555,11 +554,10 @@  lto_balanced_map (void)
 	  symtab_node snode = lto_symtab_encoder_deref (partition->encoder,
 							last_visited_node);

-	  if (symtab_function_p (snode))
+	  if (cgraph_node *node = snode->try_function ())
 	    {
 	      struct cgraph_edge *edge;

-	      node = cgraph (snode);
 	      refs = &node->symbol.ref_list;

 	      last_visited_node++;
@@ -611,7 +609,7 @@  lto_balanced_map (void)
 	  /* Compute boundary cost of IPA REF edges and at the same time look into
 	     variables referenced from current partition and try to add them.  */
 	  for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++)
-	    if (symtab_variable_p (ref->referred))
+	    if (ref->referred->is_variable ())
 	      {
 		int index;

@@ -645,7 +643,7 @@  lto_balanced_map (void)
 		  cost++;
 	      }
 	  for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++)
-	    if (symtab_variable_p (ref->referring))
+	    if (ref->referring->is_variable ())
 	      {
 		int index;

Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(revision 192010)
+++ gcc/varasm.c	(working copy)
@@ -2221,7 +2221,7 @@  mark_decl_referenced (tree decl)
     }
   else if (TREE_CODE (decl) == VAR_DECL)
     {
-      struct varpool_node *node = varpool_node (decl);
+      struct varpool_node *node = varpool_node_for_decl (decl);
       /* C++ frontend use mark_decl_references to force COMDAT variables
          to be output that might appear dead otherwise.  */
       node->symbol.force_output = true;
@@ -5549,7 +5549,7 @@  assemble_alias (tree decl, tree target)
   if (TREE_CODE (decl) == FUNCTION_DECL)
     cgraph_get_create_node (decl)->alias = true;
   else
-    varpool_node (decl)->alias = true;
+    varpool_node_for_decl (decl)->alias = true;

   /* If the target has already been emitted, we don't have to queue the
      alias.  This saves a tad of memory.  */
Index: gcc/symtab.c
===================================================================
--- gcc/symtab.c	(revision 192010)
+++ gcc/symtab.c	(working copy)
@@ -104,7 +104,7 @@  eq_assembler_name (const void *p1, const
 static void
 insert_to_assembler_name_hash (symtab_node node)
 {
-  if (symtab_variable_p (node) && DECL_HARD_REGISTER (node->symbol.decl))
+  if (node->is_variable () && DECL_HARD_REGISTER (node->symbol.decl))
     return;
   gcc_checking_assert (!node->symbol.previous_sharing_asm_name
 		       && !node->symbol.next_sharing_asm_name);
@@ -252,8 +252,8 @@  symtab_unregister_node (symtab_node node
   if (*slot == node)
     {
       symtab_node replacement_node = NULL;
-      if (symtab_function_p (node))
-	replacement_node = (symtab_node)cgraph_find_replacement_node (cgraph (node));
+      if (cgraph_node *cnode = node->try_function ())
+	replacement_node = (symtab_node)cgraph_find_replacement_node (cnode);
       if (!replacement_node)
 	htab_clear_slot (symtab_hash, slot);
       else
@@ -294,10 +294,10 @@  symtab_get_node (const_tree decl)
 void
 symtab_remove_node (symtab_node node)
 {
-  if (symtab_function_p (node))
-    cgraph_remove_node (cgraph (node));
-  else if (symtab_variable_p (node))
-    varpool_remove_node (varpool (node));
+  if (cgraph_node *cnode = node->try_function ())
+    cgraph_remove_node (cnode);
+  else if (varpool_node *vnode = node->try_variable ())
+    varpool_remove_node (vnode);
 }

 /* Initalize asm name hash unless.  */
@@ -538,10 +538,10 @@  dump_symtab_base (FILE *f, symtab_node n
 void
 dump_symtab_node (FILE *f, symtab_node node)
 {
-  if (symtab_function_p (node))
-    dump_cgraph_node (f, cgraph (node));
-  else if (symtab_variable_p (node))
-    dump_varpool_node (f, varpool (node));
+  if (cgraph_node *cnode = node->try_function ())
+    dump_cgraph_node (f, cnode);
+  else if (varpool_node *vnode = node->try_variable ())
+    dump_varpool_node (f, vnode);
 }

 /* Dump symbol table.  */
@@ -579,7 +579,7 @@  verify_symtab_base (symtab_node node)
   bool error_found = false;
   symtab_node hashed_node;

-  if (symtab_function_p (node))
+  if (node->is_function ())
     {
       if (TREE_CODE (node->symbol.decl) != FUNCTION_DECL)
 	{
@@ -587,7 +587,7 @@  verify_symtab_base (symtab_node node)
           error_found = true;
 	}
     }
-  else if (symtab_variable_p (node))
+  else if (node->is_variable ())
     {
       if (TREE_CODE (node->symbol.decl) != VAR_DECL)
 	{
@@ -622,7 +622,7 @@  verify_symtab_base (symtab_node node)
 	  hashed_node = hashed_node->symbol.next_sharing_asm_name;
 	}
       if (!hashed_node
-          && !(symtab_variable_p (node) || DECL_HARD_REGISTER
(node->symbol.decl)))
+          && !(node->is_variable () || DECL_HARD_REGISTER (node->symbol.decl)))
 	{
           error ("node not found in symtab assembler name hash");
           error_found = true;
@@ -676,8 +676,8 @@  verify_symtab_node (symtab_node node)
     return;

   timevar_push (TV_CGRAPH_VERIFY);
-  if (symtab_function_p (node))
-    verify_cgraph_node (cgraph (node));
+  if (cgraph_node *cnode = node->try_function ())
+    verify_cgraph_node (cnode);
   else
     if (verify_symtab_base (node))
       {
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 192010)
+++ gcc/passes.c	(working copy)
@@ -201,7 +201,7 @@  rest_of_decl_compilation (tree decl,
     ;
   else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)
 	   && TREE_STATIC (decl))
-    varpool_node (decl);
+    varpool_node_for_decl (decl);
 }

 /* Called after finishing a record, union or enumeral type.  */
Index: gcc/varpool.c
===================================================================
--- gcc/varpool.c	(revision 192010)
+++ gcc/varpool.c	(working copy)
@@ -39,7 +39,7 @@  along with GCC; see the file COPYING3.

 /* Return varpool node assigned to DECL.  Create new one when needed.  */
 struct varpool_node *
-varpool_node (tree decl)
+varpool_node_for_decl (tree decl)
 {
   struct varpool_node *node = varpool_get_node (decl);
   gcc_assert (TREE_CODE (decl) == VAR_DECL
@@ -114,9 +114,9 @@  debug_varpool (void)
 struct varpool_node *
 varpool_node_for_asm (tree asmname)
 {
-  symtab_node node = symtab_node_for_asm (asmname);
-  if (node && symtab_variable_p (node))
-    return varpool (node);
+  if (symtab_node node = symtab_node_for_asm (asmname))
+    if (varpool_node *vnode = node->try_variable ())
+      return vnode;
   return NULL;
 }

@@ -192,7 +192,7 @@  varpool_add_new_variable (tree decl)
 {
   struct varpool_node *node;
   varpool_finalize_decl (decl);
-  node = varpool_node (decl);
+  node = varpool_node_for_decl (decl);
   if (varpool_externally_visible_p (node, false))
     node->symbol.externally_visible = true;
 }
@@ -232,7 +232,7 @@  varpool_analyze_node (struct varpool_nod
     }
   if (node->alias && node->alias_of)
     {
-      struct varpool_node *tgt = varpool_node (node->alias_of);
+      struct varpool_node *tgt = varpool_node_for_decl (node->alias_of);
       struct varpool_node *n;

       for (n = tgt; n && n->alias;
@@ -378,16 +378,21 @@  varpool_remove_unreferenced_decls (void)
 	  for (next = node->symbol.same_comdat_group;
 	       next != (symtab_node)node;
 	       next = next->symbol.same_comdat_group)
-	    if (symtab_variable_p (next)
-		&& varpool (next)->analyzed)
-	      enqueue_node (varpool (next), &first);
+	    {
+	      varpool_node *vnext = next->try_variable ();
+	      if (vnext && vnext->analyzed)
+		enqueue_node (vnext, &first);
+	    }
 	}
       for (i = 0; ipa_ref_list_reference_iterate
(&node->symbol.ref_list, i, ref); i++)
-	if (symtab_variable_p (ref->referred)
-	    && (!DECL_EXTERNAL (ref->referred->symbol.decl)
-		|| varpool (ref->referred)->alias)
-	    && varpool (ref->referred)->analyzed)
-	  enqueue_node (varpool (ref->referred), &first);
+	{
+	  varpool_node *vnode = ref->referred->try_variable ();
+	  if (vnode
+	      && (!DECL_EXTERNAL (ref->referred->symbol.decl)
+		  || vnode->alias)
+	      && vnode->analyzed)
+	    enqueue_node (vnode, &first);
+	}
     }
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file, "\nRemoving variables:");
@@ -461,7 +466,7 @@  add_new_static_var (tree type)
   DECL_CONTEXT (new_decl) = NULL_TREE;
   DECL_ABSTRACT (new_decl) = 0;
   lang_hooks.dup_lang_specific_decl (new_decl);
-  new_node = varpool_node (new_decl);
+  new_node = varpool_node_for_decl (new_decl);
   varpool_finalize_decl (new_decl);

   return new_node->symbol.decl;
@@ -477,7 +482,7 @@  varpool_create_variable_alias (tree alia

   gcc_assert (TREE_CODE (decl) == VAR_DECL);
   gcc_assert (TREE_CODE (alias) == VAR_DECL);
-  alias_node = varpool_node (alias);
+  alias_node = varpool_node_for_decl (alias);
   alias_node->alias = 1;
   alias_node->finalized = 1;
   alias_node->alias_of = decl;
Index: gcc/lto-streamer.h
===================================================================
--- gcc/lto-streamer.h	(revision 192010)
+++ gcc/lto-streamer.h	(working copy)
@@ -1120,7 +1120,7 @@  lsei_next_function_in_partition (lto_sym
 {
   lsei_next (lsei);
   while (!lsei_end_p (*lsei)
-	 && (!symtab_function_p (lsei_node (*lsei))
+	 && (!lsei_node (*lsei)->is_function ()
 	     || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
(*lsei))))
     lsei_next (lsei);