public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Use conditional casting with symtab_node
@ 2012-09-18 18:02 Lawrence Crowl
  2012-09-18 18:09 ` Eric Botcazou
                   ` (2 more replies)
  0 siblings, 3 replies; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-18 18:02 UTC (permalink / raw)
  To: gcc-patches List, Jan Hubicka; +Cc: Diego Novillo

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, a little
restructuring is required to pull out the secondary conditions.  For example,

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

becomes

  if (varpool_node *vnode = node->try_variable ())
    if (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_tree.


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


Tested on x86_64.


Okay for trunk?


Index: gcc/ChangeLog

2012-09-18  Lawrence Crowl  <crowl@google.com

	* cgraph.h (varpool_node): Rename to varpool_node_for_tree.
	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.
	* graphunit.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 191403)
+++ gcc/lto-symtab.c	(working copy)
@@ -743,7 +743,7 @@ lto_symtab_merge_cgraph_nodes_1 (void **
 	{
 	  if (!prevailing->vnode)
 	    {
-	      prevailing->vnode = varpool_node (prevailing->decl);
+	      prevailing->vnode = varpool_node_for_tree (prevailing->decl);
 	      prevailing->vnode->alias = true;
 	    }
 	  lto_varpool_replace_node (e->vnode, prevailing->vnode);
Index: gcc/cgraphbuild.c
===================================================================
--- gcc/cgraphbuild.c	(revision 191403)
+++ 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_tree (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_tree (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_tree (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_tree (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_tree (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_tree (decl);
   struct record_reference_ctx ctx = {false, NULL};

   ctx.varpool_node = node;
Index: gcc/cgraph.c
===================================================================
--- gcc/cgraph.c	(revision 191403)
+++ gcc/cgraph.c	(working copy)
@@ -506,9 +506,10 @@ 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 (; node; node = node->symbol.next_sharing_asm_name)
+    if (cgraph_node *cn = node->try_function ())
+      if (!cn->global.inlined_to)
+	return cn;
   return NULL;
 }

Index: gcc/cgraph.h
===================================================================
--- gcc/cgraph.h	(revision 191403)
+++ gcc/cgraph.h	(working copy)
@@ -448,13 +448,46 @@ 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;
 };

+inline bool
+symtab_node_def::is_function ()
+{
+  return symbol.type == SYMTAB_FUNCTION;
+}
+
+inline bool
+symtab_node_def::is_variable ()
+{
+  return symbol.type == SYMTAB_VARIABLE;
+}
+
+inline cgraph_node *
+symtab_node_def::try_function ()
+{
+  return is_function () ? &x_function : 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;
@@ -677,7 +710,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_tree (tree);
 struct varpool_node *varpool_node_for_asm (tree asmname);
 void varpool_mark_needed_node (struct varpool_node *);
 void debug_varpool (void);
@@ -705,19 +738,6 @@ bool varpool_for_node_and_aliases (struc
 			           void *, bool);
 void varpool_add_new_variable (tree);

-/* 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 *
@@ -791,8 +811,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;
 }
@@ -804,8 +824,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;
 }
@@ -822,9 +842,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);
+      if (varpool_node *vnode = node->try_variable ())
+	if (DECL_INITIAL (node->symbol.decl))
+	  return vnode;
     }
   return NULL;
 }
@@ -836,9 +856,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);
+      if (varpool_node *vnode1 = node1->try_variable ())
+	if (DECL_INITIAL (node1->symbol.decl))
+	  return vnode1;
     }
   return NULL;
 }
@@ -855,8 +875,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);
+      if (varpool_node *vnode = node->try_variable ())
+	if (vnode->analyzed)
+	  return vnode;
     }
   return NULL;
 }
@@ -868,8 +889,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);
+      if (varpool_node *vnode1 = node1->try_variable ())
+	if (vnode1->analyzed)
+	  return vnode1;
     }
   return NULL;
 }
@@ -885,8 +907,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);
+      if (cgraph_node *cn = node->try_function ())
+	if (cn->analyzed)
+	  return cn;
     }
   return NULL;
 }
@@ -898,8 +921,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);
+      if (cgraph_node *cn1 = node1->try_function ())
+	if (cn1->analyzed)
+	  return cn1;
     }
   return NULL;
 }
@@ -916,8 +940,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;
 }
@@ -929,8 +953,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;
 }
@@ -958,9 +982,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);
+      if (cgraph_node *cn = node->try_function ())
+	if (cgraph_function_with_gimple_body_p (cn))
+	  return cn;
     }
   return NULL;
 }
@@ -972,9 +996,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);
+      if (cgraph_node *cn1 = node1->try_function ())
+	if (cgraph_function_with_gimple_body_p (cn1))
+	  return cn1;
     }
   return NULL;
 }
@@ -1173,7 +1197,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;
 }
@@ -1187,7 +1211,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;
 }
Index: gcc/tree-emutls.c
===================================================================
--- gcc/tree-emutls.c	(revision 191403)
+++ 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_tree (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_tree (to);
   else if (!alias_of)
     varpool_add_new_variable (to);
   else
Index: gcc/ipa-reference.c
===================================================================
--- gcc/ipa-reference.c	(revision 191403)
+++ 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,29 +992,31 @@ 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))
-	  && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder))
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      if (varpool_node *vnode = snode->try_variable ())
 	{
-	  tree decl = vnode->symbol.decl;
-	  bitmap_set_bit (ltrans_statics, DECL_UID (decl));
-	  splay_tree_insert (reference_vars_to_consider,
-			     DECL_UID (decl), (splay_tree_value)decl);
-	  ltrans_statics_bitcount ++;
+	  if (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;
+	      bitmap_set_bit (ltrans_statics, DECL_UID (decl));
+	      splay_tree_insert (reference_vars_to_consider,
+				 DECL_UID (decl), (splay_tree_value)decl);
+	      ltrans_statics_bitcount ++;
+	    }
 	}
     }


   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))
-	  count++;
+      {
+	symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+	if (cgraph_node *cnode = snode->try_function ())
+	  if (write_node_summary_p (cnode, encoder, ltrans_statics))
+	    count++;
+      }

   streamer_write_uhwi_stream (ob->main_stream, count);
   if (count)
@@ -1027,24 +1027,22 @@ 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))
-	  {
-	    ipa_reference_optimization_summary_t info;
-	    int node_ref;
+	symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+	if (cgraph_node *cnode = snode->try_function ())
+	  if (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);
-	    streamer_write_uhwi_stream (ob->main_stream, node_ref);
+	      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,
-			       ltrans_statics_bitcount);
-	    stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
-			       ltrans_statics_bitcount);
-	  }
+	      stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
+			         ltrans_statics_bitcount);
+	      stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
+			         ltrans_statics_bitcount);
+	    }
       }
   BITMAP_FREE (ltrans_statics);
   lto_destroy_simple_output_block (ob);
Index: gcc/cgraphunit.c
===================================================================
--- gcc/cgraphunit.c	(revision 191403)
+++ gcc/cgraphunit.c	(working copy)
@@ -388,8 +388,9 @@ 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)
-    return true;
+  if (cgraph_node *cn = node->try_function ())
+    if (cn->callers)
+      return true;
   return false;
 }

@@ -818,7 +819,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_tree (decl);

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

@@ -845,6 +846,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  */

@@ -879,13 +909,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)
@@ -912,49 +936,50 @@ cgraph_analyze_functions (void)
 	  changed = true;
 	  node = first;
 	  first = (symtab_node)first->symbol.aux;
-	  if (symtab_function_p (node) && cgraph (node)->local.finalized)
+	  if (cgraph_node *cnode = node->try_function ())
 	    {
-	      struct cgraph_edge *edge;
-	      struct cgraph_node *cnode;
-	      tree decl;
-
-	      cnode = cgraph (node);
-	      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  */
-	      if (!DECL_STRUCT_FUNCTION (decl)
-		  && (!cnode->alias || !cnode->thunk.alias)
-		  && !cnode->thunk.thunk_p)
+	      if (cnode->local.finalized)
 		{
-		  cgraph_reset_node (cnode);
-		  cnode->local.redefined_extern_inline = true;
-		  continue;
-		}
+		  struct cgraph_edge *edge;
+		  tree decl = cnode->symbol.decl;

-	      if (!cnode->analyzed)
-		cgraph_analyze_function (cnode);
+		  /* ??? 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)
+		    {
+		      cgraph_reset_node (cnode);
+		      cnode->local.redefined_extern_inline = true;
+		      continue;
+		    }

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

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

 	  if (node->symbol.same_comdat_group)
 	    {
@@ -965,9 +990,9 @@ 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 ();
 	}
     }
@@ -994,10 +1019,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)
@@ -1079,7 +1103,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)
@@ -1088,7 +1112,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 191403)
+++ gcc/cp/decl2.c	(working copy)
@@ -1773,7 +1773,7 @@ import_export_class (tree ctype)
 static bool
 var_finalized_p (tree var)
 {
-  return varpool_node (var)->finalized;
+  return varpool_node_for_tree (var)->finalized;
 }

 /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
@@ -1891,7 +1891,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_tree (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 191403)
+++ 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 191403)
+++ 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
       {
@@ -719,9 +719,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)
@@ -785,8 +784,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);
 	
@@ -972,7 +971,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_tree (var_decl);
   node->symbol.order = order;
   if (order >= symtab_order)
     symtab_order = order + 1;
@@ -1133,14 +1132,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)
@@ -1149,9 +1148,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;
@@ -1163,7 +1162,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;
 }

@@ -1437,7 +1436,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);
@@ -1447,19 +1445,22 @@ 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);
+      if (cgraph_node *cnode = node->try_function ())
+	if (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)))
-	{
-	  streamer_write_uhwi (ob, i);
-	  output_node_opt_summary (ob, cgraph (node), encoder);
-	}
+      symtab_node node = lto_symtab_encoder_deref (encoder, i);
+      if (cgraph_node *cnode = node->try_function ())
+	if (output_cgraph_opt_summary_p (cnode))
+	  {
+	    streamer_write_uhwi (ob, i);
+	    output_node_opt_summary (ob, cnode, encoder);
+	  }
     }
   produce_asm (ob, NULL);
   destroy_output_block (ob);
Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c	(revision 191403)
+++ gcc/lto-streamer-out.c	(working copy)
@@ -975,7 +975,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 ();
@@ -991,27 +990,25 @@ 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)
-	  && !node->alias
-	  && !node->thunk.thunk_p)
-	{
+      if (cgraph_node *node = snode->try_function ())
+	if (lto_symtab_encoder_encode_body_p (encoder, node)
+	    && !node->alias
+	    && !node->thunk.thunk_p)
+	  {
 #ifdef ENABLE_CHECKING
-	  gcc_assert (!bitmap_bit_p (output, DECL_UID (node->symbol.decl)));
-	  bitmap_set_bit (output, DECL_UID (node->symbol.decl));
+	    gcc_assert (!bitmap_bit_p (output, DECL_UID (node->symbol.decl)));
+	    bitmap_set_bit (output, DECL_UID (node->symbol.decl));
 #endif
-	  decl_state = lto_new_out_decl_state ();
-	  lto_push_out_decl_state (decl_state);
-	  if (gimple_has_body_p (node->symbol.decl))
-	    output_function (node);
-	  else
-	    copy_function (node);
-	  gcc_assert (lto_get_out_decl_state () == decl_state);
-	  lto_pop_out_decl_state ();
-	  lto_record_function_out_decl_state (node->symbol.decl, decl_state);
-	}
+	    decl_state = lto_new_out_decl_state ();
+	    lto_push_out_decl_state (decl_state);
+	    if (gimple_has_body_p (node->symbol.decl))
+	      output_function (node);
+	    else
+	      copy_function (node);
+	    gcc_assert (lto_get_out_decl_state () == decl_state);
+	    lto_pop_out_decl_state ();
+	    lto_record_function_out_decl_state (node->symbol.decl, decl_state);
+	  }
     }

   /* Emit the callgraph after emitting function bodies.  This needs to
@@ -1288,8 +1285,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;
@@ -1305,73 +1300,77 @@ 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)))
-	continue;
-      node = cgraph (lto_symtab_encoder_deref (encoder, i));
-      if (DECL_EXTERNAL (node->symbol.decl))
-	continue;
-      if (DECL_COMDAT (node->symbol.decl)
-	  && cgraph_comdat_can_be_unshared_p (node))
-	continue;
-      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
-	continue;
-      write_symbol (cache, &stream, node->symbol.decl, seen, false);
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      if (cgraph_node *cnode = snode->try_function ())
+	{
+	  if (DECL_EXTERNAL (cnode->symbol.decl))
+	    continue;
+	  if (DECL_COMDAT (cnode->symbol.decl)
+	      && cgraph_comdat_can_be_unshared_p (cnode))
+	    continue;
+	  if ((cnode->alias && !cnode->thunk.alias) || cnode->global.inlined_to)
+	    continue;
+	  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)))
-	continue;
-      node = cgraph (lto_symtab_encoder_deref (encoder, i));
-      if (!DECL_EXTERNAL (node->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)
-	continue;
-      if (DECL_COMDAT (node->symbol.decl)
-	  && cgraph_comdat_can_be_unshared_p (node))
-	continue;
-      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
-	continue;
-      write_symbol (cache, &stream, node->symbol.decl, seen, false);
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      if (cgraph_node *cnode = snode->try_function ())
+	{
+	  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 (!cnode->symbol.address_taken && !cnode->callers)
+	    continue;
+	  if (DECL_COMDAT (cnode->symbol.decl)
+	      && cgraph_comdat_can_be_unshared_p (cnode))
+	    continue;
+	  if ((cnode->alias && !cnode->thunk.alias) || cnode->global.inlined_to)
+	    continue;
+	  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)))
-	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. */
-      if (DECL_COMDAT (vnode->symbol.decl)
-	  && !vnode->symbol.force_output
-	  && vnode->finalized
-	  && DECL_VIRTUAL_P (vnode->symbol.decl))
-	continue;
-      if (vnode->alias && !vnode->alias_of)
-	continue;
-      write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      if (varpool_node *vnode = snode->try_variable ())
+	{
+	  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. */
+	  if (DECL_COMDAT (vnode->symbol.decl)
+	      && !vnode->symbol.force_output
+	      && vnode->finalized
+	      && DECL_VIRTUAL_P (vnode->symbol.decl))
+	    continue;
+	  if (vnode->alias && !vnode->alias_of)
+	    continue;
+	  write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
+	}
     }
   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
-	continue;
-      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
-      if (!DECL_EXTERNAL (vnode->symbol.decl))
-	continue;
-      if (DECL_COMDAT (vnode->symbol.decl)
-	  && !vnode->symbol.force_output
-	  && vnode->finalized
-	  && DECL_VIRTUAL_P (vnode->symbol.decl))
-	continue;
-      if (vnode->alias && !vnode->alias_of)
-	continue;
-      write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      if (varpool_node *vnode = snode->try_variable ())
+	{
+	  if (!DECL_EXTERNAL (vnode->symbol.decl))
+	    continue;
+	  if (DECL_COMDAT (vnode->symbol.decl)
+	      && !vnode->symbol.force_output
+	      && vnode->finalized
+	      && DECL_VIRTUAL_P (vnode->symbol.decl))
+	    continue;
+	  if (vnode->alias && !vnode->alias_of)
+	    continue;
+	  write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
+	}
     }

   lto_write_stream (&stream);
Index: gcc/ada/gcc-interface/utils.c
===================================================================
--- gcc/ada/gcc-interface/utils.c	(revision 191403)
+++ 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_tree (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 191403)
+++ 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)
@@ -331,19 +329,21 @@ 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)
-	  && DECL_EXTERNAL (node->symbol.decl)
-	  && !varpool (node)->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++)
-	    enqueue_node (ref->referred, &first, reachable);
-        }
+      /* When we see constructor of external variable, keep referred nodes
+	 in the boundary.  This will also hold initializers of the external
+	 vars NODE refers to.  */
+      if (varpool_node *vnode = node->try_variable ())
+	if (DECL_EXTERNAL (node->symbol.decl)
+	    && !vnode->alias
+	    && in_boundary_p)
+	  {
+	    struct ipa_ref *ref;
+	    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 +526,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 191403)
+++ gcc/ipa-inline-analysis.c	(working copy)
@@ -3816,65 +3816,68 @@ 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);
+      if (cgraph_node *cnode = snode->try_function ())
+	if (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)
-	{
-	  struct inline_summary *info = inline_summary (node);
-	  struct bitpack_d bp;
-	  struct cgraph_edge *edge;
-	  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);
-	  streamer_write_hwi (ob, info->self_time);
-	  bp = bitpack_create (ob->main_stream);
-	  bp_pack_value (&bp, info->inlinable, 1);
-	  streamer_write_bitpack (&bp);
-	  streamer_write_uhwi (ob, VEC_length (condition, info->conds));
-	  for (i = 0; VEC_iterate (condition, info->conds, i, c); i++)
-	    {
-	      streamer_write_uhwi (ob, c->operand_num);
-	      streamer_write_uhwi (ob, c->code);
-	      stream_write_tree (ob, c->val, true);
-	      bp = bitpack_create (ob->main_stream);
-	      bp_pack_value (&bp, c->agg_contents, 1);
-	      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, VEC_length (size_time_entry, info->entry));
-	  for (i = 0;
-	       VEC_iterate (size_time_entry, info->entry, i, e);
-	       i++)
-	    {
-	      streamer_write_uhwi (ob, e->size);
-	      streamer_write_uhwi (ob, e->time);
-	      write_predicate (ob, &e->predicate);
-	    }
-	  write_predicate (ob, info->loop_iterations);
-	  write_predicate (ob, info->loop_stride);
-	  for (edge = node->callees; edge; edge = edge->next_callee)
-	    write_inline_edge_summary (ob, edge);
-	  for (edge = node->indirect_calls; edge; edge = edge->next_callee)
-	    write_inline_edge_summary (ob, edge);
+      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
+      if (cgraph_node *cnode = snode->try_function ())
+	if ((node = cnode)->analyzed)
+	  {
+	    struct inline_summary *info = inline_summary (node);
+	    struct bitpack_d bp;
+	    struct cgraph_edge *edge;
+	    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);
+	    streamer_write_hwi (ob, info->self_time);
+	    bp = bitpack_create (ob->main_stream);
+	    bp_pack_value (&bp, info->inlinable, 1);
+	    streamer_write_bitpack (&bp);
+	    streamer_write_uhwi (ob, VEC_length (condition, info->conds));
+	    for (i = 0; VEC_iterate (condition, info->conds, i, c); i++)
+	      {
+		streamer_write_uhwi (ob, c->operand_num);
+		streamer_write_uhwi (ob, c->code);
+		stream_write_tree (ob, c->val, true);
+		bp = bitpack_create (ob->main_stream);
+		bp_pack_value (&bp, c->agg_contents, 1);
+		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, VEC_length (size_time_entry, info->entry));
+	    for (i = 0;
+		 VEC_iterate (size_time_entry, info->entry, i, e);
+		 i++)
+	      {
+		streamer_write_uhwi (ob, e->size);
+		streamer_write_uhwi (ob, e->time);
+		write_predicate (ob, &e->predicate);
+	      }
+	    write_predicate (ob, info->loop_iterations);
+	    write_predicate (ob, info->loop_stride);
+	    for (edge = node->callees; edge; edge = edge->next_callee)
+	      write_inline_edge_summary (ob, edge);
+	    for (edge = node->indirect_calls; edge; edge = edge->next_callee)
+	      write_inline_edge_summary (ob, edge);
 	}
     }
   streamer_write_char_stream (ob->main_stream, 0);
Index: gcc/lto/lto.c
===================================================================
--- gcc/lto/lto.c	(revision 191403)
+++ gcc/lto/lto.c	(working copy)
@@ -2619,12 +2619,16 @@ 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)))
-		    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)");
+		  if (cgraph_node *cnode = node->try_function ())
+		    {
+		      if (lto_symtab_encoder_encode_body_p (part->encoder, cnode))
+		      fprintf (cgraph_dump_file, "(body included)");
+		    }
+		  else if (varpool_node *vnode = node->try_variable ())
+		    {
+		      if (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 191403)
+++ 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)
-    return SYMBOL_DUPLICATE;
+  if (cgraph_node *cnode = node->try_function ())
+    if (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 191403)
+++ 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_tree (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_tree (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 191403)
+++ gcc/symtab.c	(working copy)
@@ -239,8 +239,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
@@ -281,10 +281,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);
 }

 /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
@@ -514,10 +514,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.  */
@@ -555,7 +555,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)
 	{
@@ -563,7 +563,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)
 	{
@@ -651,8 +651,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 191403)
+++ 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_tree (decl);
 }

 /* Called after finishing a record, union or enumeral type.  */
Index: gcc/varpool.c
===================================================================
--- gcc/varpool.c	(revision 191403)
+++ 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_tree (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_tree (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_tree (node->alias_of);
       struct varpool_node *n;

       for (n = tgt; n && n->alias;
@@ -374,16 +374,15 @@ 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);
+	    if (varpool_node *vnext = next->try_variable ())
+	      if (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);
+	if (varpool_node *vnode = ref->referred->try_variable ())
+	  if ((!DECL_EXTERNAL (ref->referred->symbol.decl) || vnode->alias)
+	      && vnode->analyzed)
+	    enqueue_node (vnode, &first);
     }
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file, "\nRemoving variables:");
@@ -457,7 +456,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_tree (new_decl);
   varpool_finalize_decl (new_decl);

   return new_node->symbol.decl;
@@ -473,7 +472,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_tree (alias);
   alias_node->alias = 1;
   alias_node->finalized = 1;
   alias_node->alias_of = decl;
Index: gcc/lto-streamer.h
===================================================================
--- gcc/lto-streamer.h	(revision 191403)
+++ gcc/lto-streamer.h	(working copy)
@@ -1121,7 +1121,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);
 }
@@ -1134,7 +1134,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);

@@ -1147,7 +1147,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);
 }
@@ -1160,7 +1160,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

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

* Re: Use conditional casting with symtab_node
  2012-09-18 18:02 Use conditional casting with symtab_node Lawrence Crowl
@ 2012-09-18 18:09 ` Eric Botcazou
  2012-09-18 18:37   ` Lawrence Crowl
  2012-09-18 19:57 ` Richard Guenther
  2012-09-22  6:07 ` Lawrence Crowl
  2 siblings, 1 reply; 47+ messages in thread
From: Eric Botcazou @ 2012-09-18 18:09 UTC (permalink / raw)
  To: Lawrence Crowl; +Cc: gcc-patches, Jan Hubicka, Diego Novillo

> When, the property test is embedded within a larger condition, a little
> restructuring is required to pull out the secondary conditions.  For
> example,
> 
>   if (symtab_variable_p (node)
>       && varpool (node)->finalized)
>     varpool_analyze_node (varpool (node));
> 
> becomes
> 
>   if (varpool_node *vnode = node->try_variable ())
>     if (vnode->finalized)
>       varpool_analyze_node (vnode);

Please avoid cascading if's like this, use the existing && idiom instead.

-- 
Eric Botcazou

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

* Re: Use conditional casting with symtab_node
  2012-09-18 18:09 ` Eric Botcazou
@ 2012-09-18 18:37   ` Lawrence Crowl
  2012-09-19  7:31     ` Eric Botcazou
  0 siblings, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-18 18:37 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Jan Hubicka, Diego Novillo

On 9/18/12, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> When, the property test is embedded within a larger condition, a little
>> restructuring is required to pull out the secondary conditions.  For
>> example,
>>
>>   if (symtab_variable_p (node)
>>       && varpool (node)->finalized)
>>     varpool_analyze_node (varpool (node));
>>
>> becomes
>>
>>   if (varpool_node *vnode = node->try_variable ())
>>     if (vnode->finalized)
>>       varpool_analyze_node (vnode);
>
> Please avoid cascading if's like this, use the existing && idiom instead.

The language syntax would bind the conditional into the intializer, as in

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

which does not type-match.

So, if you want the type saftey and performance, the cascade is really
unavoidable.

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-09-18 18:02 Use conditional casting with symtab_node Lawrence Crowl
  2012-09-18 18:09 ` Eric Botcazou
@ 2012-09-18 19:57 ` Richard Guenther
  2012-09-18 20:32   ` Lawrence Crowl
  2012-09-22  6:07 ` Lawrence Crowl
  2 siblings, 1 reply; 47+ messages in thread
From: Richard Guenther @ 2012-09-18 19:57 UTC (permalink / raw)
  To: Lawrence Crowl; +Cc: gcc-patches List, Jan Hubicka, Diego Novillo

On Tue, Sep 18, 2012 at 8:01 PM, Lawrence Crowl <crowl@googlers.com> wrote:
> 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, a little
> restructuring is required to pull out the secondary conditions.  For example,
>
>   if (symtab_variable_p (node)
>       && varpool (node)->finalized)
>     varpool_analyze_node (varpool (node));
>
> becomes
>
>   if (varpool_node *vnode = node->try_variable ())
>     if (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_tree.
>
>
> The new code bootstraps .616% faster with a 99% confidence of being faster.
>
>
> Tested on x86_64.
>
>
> Okay for trunk?
>
>
> Index: gcc/ChangeLog
>
> 2012-09-18  Lawrence Crowl  <crowl@google.com
>
>         * cgraph.h (varpool_node): Rename to varpool_node_for_tree.

Sure it should be varpool_node_for_decl, if any.  Or varpool_node_from_decl
(grep for what is more common)

>         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.
>         * graphunit.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 191403)
> +++ gcc/lto-symtab.c    (working copy)
> @@ -743,7 +743,7 @@ lto_symtab_merge_cgraph_nodes_1 (void **
>         {
>           if (!prevailing->vnode)
>             {
> -             prevailing->vnode = varpool_node (prevailing->decl);
> +             prevailing->vnode = varpool_node_for_tree (prevailing->decl);
>               prevailing->vnode->alias = true;
>             }
>           lto_varpool_replace_node (e->vnode, prevailing->vnode);
> Index: gcc/cgraphbuild.c
> ===================================================================
> --- gcc/cgraphbuild.c   (revision 191403)
> +++ 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_tree (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_tree (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_tree (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_tree (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_tree (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_tree (decl);
>    struct record_reference_ctx ctx = {false, NULL};
>
>    ctx.varpool_node = node;
> Index: gcc/cgraph.c
> ===================================================================
> --- gcc/cgraph.c        (revision 191403)
> +++ gcc/cgraph.c        (working copy)
> @@ -506,9 +506,10 @@ 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 (; node; node = node->symbol.next_sharing_asm_name)
> +    if (cgraph_node *cn = node->try_function ())
> +      if (!cn->global.inlined_to)
> +       return cn;
>    return NULL;
>  }
>
> Index: gcc/cgraph.h
> ===================================================================
> --- gcc/cgraph.h        (revision 191403)
> +++ gcc/cgraph.h        (working copy)
> @@ -448,13 +448,46 @@ 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;
>  };
>
> +inline bool
> +symtab_node_def::is_function ()
> +{
> +  return symbol.type == SYMTAB_FUNCTION;
> +}
> +
> +inline bool
> +symtab_node_def::is_variable ()
> +{
> +  return symbol.type == SYMTAB_VARIABLE;
> +}
> +
> +inline cgraph_node *
> +symtab_node_def::try_function ()
> +{
> +  return is_function () ? &x_function : 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;
> @@ -677,7 +710,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_tree (tree);
>  struct varpool_node *varpool_node_for_asm (tree asmname);
>  void varpool_mark_needed_node (struct varpool_node *);
>  void debug_varpool (void);
> @@ -705,19 +738,6 @@ bool varpool_for_node_and_aliases (struc
>                                    void *, bool);
>  void varpool_add_new_variable (tree);
>
> -/* 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 *
> @@ -791,8 +811,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;
>  }
> @@ -804,8 +824,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;
>  }
> @@ -822,9 +842,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);
> +      if (varpool_node *vnode = node->try_variable ())
> +       if (DECL_INITIAL (node->symbol.decl))
> +         return vnode;
>      }
>    return NULL;
>  }
> @@ -836,9 +856,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);
> +      if (varpool_node *vnode1 = node1->try_variable ())
> +       if (DECL_INITIAL (node1->symbol.decl))
> +         return vnode1;
>      }
>    return NULL;
>  }
> @@ -855,8 +875,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);
> +      if (varpool_node *vnode = node->try_variable ())
> +       if (vnode->analyzed)
> +         return vnode;
>      }
>    return NULL;
>  }
> @@ -868,8 +889,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);
> +      if (varpool_node *vnode1 = node1->try_variable ())
> +       if (vnode1->analyzed)
> +         return vnode1;
>      }
>    return NULL;
>  }
> @@ -885,8 +907,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);
> +      if (cgraph_node *cn = node->try_function ())
> +       if (cn->analyzed)
> +         return cn;
>      }
>    return NULL;
>  }
> @@ -898,8 +921,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);
> +      if (cgraph_node *cn1 = node1->try_function ())
> +       if (cn1->analyzed)
> +         return cn1;
>      }
>    return NULL;
>  }
> @@ -916,8 +940,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;
>  }
> @@ -929,8 +953,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;
>  }
> @@ -958,9 +982,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);
> +      if (cgraph_node *cn = node->try_function ())
> +       if (cgraph_function_with_gimple_body_p (cn))
> +         return cn;
>      }
>    return NULL;
>  }
> @@ -972,9 +996,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);
> +      if (cgraph_node *cn1 = node1->try_function ())
> +       if (cgraph_function_with_gimple_body_p (cn1))
> +         return cn1;
>      }
>    return NULL;
>  }
> @@ -1173,7 +1197,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;
>  }
> @@ -1187,7 +1211,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;
>  }
> Index: gcc/tree-emutls.c
> ===================================================================
> --- gcc/tree-emutls.c   (revision 191403)
> +++ 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_tree (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_tree (to);
>    else if (!alias_of)
>      varpool_add_new_variable (to);
>    else
> Index: gcc/ipa-reference.c
> ===================================================================
> --- gcc/ipa-reference.c (revision 191403)
> +++ 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,29 +992,31 @@ 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))
> -         && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder))
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      if (varpool_node *vnode = snode->try_variable ())
>         {
> -         tree decl = vnode->symbol.decl;
> -         bitmap_set_bit (ltrans_statics, DECL_UID (decl));
> -         splay_tree_insert (reference_vars_to_consider,
> -                            DECL_UID (decl), (splay_tree_value)decl);
> -         ltrans_statics_bitcount ++;
> +         if (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;
> +             bitmap_set_bit (ltrans_statics, DECL_UID (decl));
> +             splay_tree_insert (reference_vars_to_consider,
> +                                DECL_UID (decl), (splay_tree_value)decl);
> +             ltrans_statics_bitcount ++;
> +           }
>         }
>      }
>
>
>    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))
> -         count++;
> +      {
> +       symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +       if (cgraph_node *cnode = snode->try_function ())
> +         if (write_node_summary_p (cnode, encoder, ltrans_statics))
> +           count++;
> +      }
>
>    streamer_write_uhwi_stream (ob->main_stream, count);
>    if (count)
> @@ -1027,24 +1027,22 @@ 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))
> -         {
> -           ipa_reference_optimization_summary_t info;
> -           int node_ref;
> +       symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +       if (cgraph_node *cnode = snode->try_function ())
> +         if (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);
> -           streamer_write_uhwi_stream (ob->main_stream, node_ref);
> +             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,
> -                              ltrans_statics_bitcount);
> -           stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
> -                              ltrans_statics_bitcount);
> -         }
> +             stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
> +                                ltrans_statics_bitcount);
> +             stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
> +                                ltrans_statics_bitcount);
> +           }
>        }
>    BITMAP_FREE (ltrans_statics);
>    lto_destroy_simple_output_block (ob);
> Index: gcc/cgraphunit.c
> ===================================================================
> --- gcc/cgraphunit.c    (revision 191403)
> +++ gcc/cgraphunit.c    (working copy)
> @@ -388,8 +388,9 @@ 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)
> -    return true;
> +  if (cgraph_node *cn = node->try_function ())
> +    if (cn->callers)
> +      return true;
>    return false;
>  }
>
> @@ -818,7 +819,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_tree (decl);
>
>    gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
>
> @@ -845,6 +846,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  */
>
> @@ -879,13 +909,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)
> @@ -912,49 +936,50 @@ cgraph_analyze_functions (void)
>           changed = true;
>           node = first;
>           first = (symtab_node)first->symbol.aux;
> -         if (symtab_function_p (node) && cgraph (node)->local.finalized)
> +         if (cgraph_node *cnode = node->try_function ())
>             {
> -             struct cgraph_edge *edge;
> -             struct cgraph_node *cnode;
> -             tree decl;
> -
> -             cnode = cgraph (node);
> -             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  */
> -             if (!DECL_STRUCT_FUNCTION (decl)
> -                 && (!cnode->alias || !cnode->thunk.alias)
> -                 && !cnode->thunk.thunk_p)
> +             if (cnode->local.finalized)
>                 {
> -                 cgraph_reset_node (cnode);
> -                 cnode->local.redefined_extern_inline = true;
> -                 continue;
> -               }
> +                 struct cgraph_edge *edge;
> +                 tree decl = cnode->symbol.decl;
>
> -             if (!cnode->analyzed)
> -               cgraph_analyze_function (cnode);
> +                 /* ??? 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)
> +                   {
> +                     cgraph_reset_node (cnode);
> +                     cnode->local.redefined_extern_inline = true;
> +                     continue;
> +                   }
>
> -             for (edge = cnode->callees; edge; edge = edge->next_callee)
> -               if (edge->callee->local.finalized)
> -                 enqueue_node ((symtab_node)edge->callee);
> +                 if (!cnode->analyzed)
> +                   cgraph_analyze_function (cnode);
>
> -             /* 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));
> -                 origin_node->abstract_and_needed = true;
> -               }
> +                 for (edge = cnode->callees; edge; edge = edge->next_callee)
> +                   if (edge->callee->local.finalized)
> +                      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_ABSTRACT_ORIGIN (decl))
> +                   {
> +                     struct cgraph_node *origin_node
> +                         = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
> +                     origin_node->abstract_and_needed = true;
> +                   }
> +               }
> +           }
> +         else
> +           {
> +             if (varpool_node *vnode = node->try_variable ())
> +               if (vnode->finalized)
> +                 varpool_analyze_node (vnode);
>             }
> -         else if (symtab_variable_p (node)
> -                  && varpool (node)->finalized)
> -           varpool_analyze_node (varpool (node));
>
>           if (node->symbol.same_comdat_group)
>             {
> @@ -965,9 +990,9 @@ 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 ();
>         }
>      }
> @@ -994,10 +1019,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)
> @@ -1079,7 +1103,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)
> @@ -1088,7 +1112,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 191403)
> +++ gcc/cp/decl2.c      (working copy)
> @@ -1773,7 +1773,7 @@ import_export_class (tree ctype)
>  static bool
>  var_finalized_p (tree var)
>  {
> -  return varpool_node (var)->finalized;
> +  return varpool_node_for_tree (var)->finalized;
>  }
>
>  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
> @@ -1891,7 +1891,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_tree (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 191403)
> +++ 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 191403)
> +++ 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
>        {
> @@ -719,9 +719,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)
> @@ -785,8 +784,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);
>
> @@ -972,7 +971,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_tree (var_decl);
>    node->symbol.order = order;
>    if (order >= symtab_order)
>      symtab_order = order + 1;
> @@ -1133,14 +1132,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)
> @@ -1149,9 +1148,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;
> @@ -1163,7 +1162,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;
>  }
>
> @@ -1437,7 +1436,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);
> @@ -1447,19 +1445,22 @@ 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);
> +      if (cgraph_node *cnode = node->try_function ())
> +       if (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)))
> -       {
> -         streamer_write_uhwi (ob, i);
> -         output_node_opt_summary (ob, cgraph (node), encoder);
> -       }
> +      symtab_node node = lto_symtab_encoder_deref (encoder, i);
> +      if (cgraph_node *cnode = node->try_function ())
> +       if (output_cgraph_opt_summary_p (cnode))
> +         {
> +           streamer_write_uhwi (ob, i);
> +           output_node_opt_summary (ob, cnode, encoder);
> +         }
>      }
>    produce_asm (ob, NULL);
>    destroy_output_block (ob);
> Index: gcc/lto-streamer-out.c
> ===================================================================
> --- gcc/lto-streamer-out.c      (revision 191403)
> +++ gcc/lto-streamer-out.c      (working copy)
> @@ -975,7 +975,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 ();
> @@ -991,27 +990,25 @@ 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)
> -         && !node->alias
> -         && !node->thunk.thunk_p)
> -       {
> +      if (cgraph_node *node = snode->try_function ())
> +       if (lto_symtab_encoder_encode_body_p (encoder, node)
> +           && !node->alias
> +           && !node->thunk.thunk_p)
> +         {
>  #ifdef ENABLE_CHECKING
> -         gcc_assert (!bitmap_bit_p (output, DECL_UID (node->symbol.decl)));
> -         bitmap_set_bit (output, DECL_UID (node->symbol.decl));
> +           gcc_assert (!bitmap_bit_p (output, DECL_UID (node->symbol.decl)));
> +           bitmap_set_bit (output, DECL_UID (node->symbol.decl));
>  #endif
> -         decl_state = lto_new_out_decl_state ();
> -         lto_push_out_decl_state (decl_state);
> -         if (gimple_has_body_p (node->symbol.decl))
> -           output_function (node);
> -         else
> -           copy_function (node);
> -         gcc_assert (lto_get_out_decl_state () == decl_state);
> -         lto_pop_out_decl_state ();
> -         lto_record_function_out_decl_state (node->symbol.decl, decl_state);
> -       }
> +           decl_state = lto_new_out_decl_state ();
> +           lto_push_out_decl_state (decl_state);
> +           if (gimple_has_body_p (node->symbol.decl))
> +             output_function (node);
> +           else
> +             copy_function (node);
> +           gcc_assert (lto_get_out_decl_state () == decl_state);
> +           lto_pop_out_decl_state ();
> +           lto_record_function_out_decl_state (node->symbol.decl, decl_state);
> +         }
>      }
>
>    /* Emit the callgraph after emitting function bodies.  This needs to
> @@ -1288,8 +1285,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;
> @@ -1305,73 +1300,77 @@ 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)))
> -       continue;
> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
> -      if (DECL_EXTERNAL (node->symbol.decl))
> -       continue;
> -      if (DECL_COMDAT (node->symbol.decl)
> -         && cgraph_comdat_can_be_unshared_p (node))
> -       continue;
> -      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
> -       continue;
> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      if (cgraph_node *cnode = snode->try_function ())
> +       {
> +         if (DECL_EXTERNAL (cnode->symbol.decl))
> +           continue;
> +         if (DECL_COMDAT (cnode->symbol.decl)
> +             && cgraph_comdat_can_be_unshared_p (cnode))
> +           continue;
> +         if ((cnode->alias && !cnode->thunk.alias) || cnode->global.inlined_to)
> +           continue;
> +         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)))
> -       continue;
> -      node = cgraph (lto_symtab_encoder_deref (encoder, i));
> -      if (!DECL_EXTERNAL (node->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)
> -       continue;
> -      if (DECL_COMDAT (node->symbol.decl)
> -         && cgraph_comdat_can_be_unshared_p (node))
> -       continue;
> -      if ((node->alias && !node->thunk.alias) || node->global.inlined_to)
> -       continue;
> -      write_symbol (cache, &stream, node->symbol.decl, seen, false);
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      if (cgraph_node *cnode = snode->try_function ())
> +       {
> +         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 (!cnode->symbol.address_taken && !cnode->callers)
> +           continue;
> +         if (DECL_COMDAT (cnode->symbol.decl)
> +             && cgraph_comdat_can_be_unshared_p (cnode))
> +           continue;
> +         if ((cnode->alias && !cnode->thunk.alias) || cnode->global.inlined_to)
> +           continue;
> +         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)))
> -       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. */
> -      if (DECL_COMDAT (vnode->symbol.decl)
> -         && !vnode->symbol.force_output
> -         && vnode->finalized
> -         && DECL_VIRTUAL_P (vnode->symbol.decl))
> -       continue;
> -      if (vnode->alias && !vnode->alias_of)
> -       continue;
> -      write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      if (varpool_node *vnode = snode->try_variable ())
> +       {
> +         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. */
> +         if (DECL_COMDAT (vnode->symbol.decl)
> +             && !vnode->symbol.force_output
> +             && vnode->finalized
> +             && DECL_VIRTUAL_P (vnode->symbol.decl))
> +           continue;
> +         if (vnode->alias && !vnode->alias_of)
> +           continue;
> +         write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
> +       }
>      }
>    for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
>      {
> -      if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i)))
> -       continue;
> -      vnode = varpool (lto_symtab_encoder_deref (encoder, i));
> -      if (!DECL_EXTERNAL (vnode->symbol.decl))
> -       continue;
> -      if (DECL_COMDAT (vnode->symbol.decl)
> -         && !vnode->symbol.force_output
> -         && vnode->finalized
> -         && DECL_VIRTUAL_P (vnode->symbol.decl))
> -       continue;
> -      if (vnode->alias && !vnode->alias_of)
> -       continue;
> -      write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      if (varpool_node *vnode = snode->try_variable ())
> +       {
> +         if (!DECL_EXTERNAL (vnode->symbol.decl))
> +           continue;
> +         if (DECL_COMDAT (vnode->symbol.decl)
> +             && !vnode->symbol.force_output
> +             && vnode->finalized
> +             && DECL_VIRTUAL_P (vnode->symbol.decl))
> +           continue;
> +         if (vnode->alias && !vnode->alias_of)
> +           continue;
> +         write_symbol (cache, &stream, vnode->symbol.decl, seen, false);
> +       }
>      }
>
>    lto_write_stream (&stream);
> Index: gcc/ada/gcc-interface/utils.c
> ===================================================================
> --- gcc/ada/gcc-interface/utils.c       (revision 191403)
> +++ 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_tree (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 191403)
> +++ 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)
> @@ -331,19 +329,21 @@ 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)
> -         && DECL_EXTERNAL (node->symbol.decl)
> -         && !varpool (node)->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++)
> -           enqueue_node (ref->referred, &first, reachable);
> -        }
> +      /* When we see constructor of external variable, keep referred nodes
> +        in the boundary.  This will also hold initializers of the external
> +        vars NODE refers to.  */
> +      if (varpool_node *vnode = node->try_variable ())
> +       if (DECL_EXTERNAL (node->symbol.decl)
> +           && !vnode->alias
> +           && in_boundary_p)
> +         {
> +           struct ipa_ref *ref;
> +           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 +526,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 191403)
> +++ gcc/ipa-inline-analysis.c   (working copy)
> @@ -3816,65 +3816,68 @@ 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);
> +      if (cgraph_node *cnode = snode->try_function ())
> +       if (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)
> -       {
> -         struct inline_summary *info = inline_summary (node);
> -         struct bitpack_d bp;
> -         struct cgraph_edge *edge;
> -         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);
> -         streamer_write_hwi (ob, info->self_time);
> -         bp = bitpack_create (ob->main_stream);
> -         bp_pack_value (&bp, info->inlinable, 1);
> -         streamer_write_bitpack (&bp);
> -         streamer_write_uhwi (ob, VEC_length (condition, info->conds));
> -         for (i = 0; VEC_iterate (condition, info->conds, i, c); i++)
> -           {
> -             streamer_write_uhwi (ob, c->operand_num);
> -             streamer_write_uhwi (ob, c->code);
> -             stream_write_tree (ob, c->val, true);
> -             bp = bitpack_create (ob->main_stream);
> -             bp_pack_value (&bp, c->agg_contents, 1);
> -             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, VEC_length (size_time_entry, info->entry));
> -         for (i = 0;
> -              VEC_iterate (size_time_entry, info->entry, i, e);
> -              i++)
> -           {
> -             streamer_write_uhwi (ob, e->size);
> -             streamer_write_uhwi (ob, e->time);
> -             write_predicate (ob, &e->predicate);
> -           }
> -         write_predicate (ob, info->loop_iterations);
> -         write_predicate (ob, info->loop_stride);
> -         for (edge = node->callees; edge; edge = edge->next_callee)
> -           write_inline_edge_summary (ob, edge);
> -         for (edge = node->indirect_calls; edge; edge = edge->next_callee)
> -           write_inline_edge_summary (ob, edge);
> +      symtab_node snode = lto_symtab_encoder_deref (encoder, i);
> +      if (cgraph_node *cnode = snode->try_function ())
> +       if ((node = cnode)->analyzed)
> +         {
> +           struct inline_summary *info = inline_summary (node);
> +           struct bitpack_d bp;
> +           struct cgraph_edge *edge;
> +           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);
> +           streamer_write_hwi (ob, info->self_time);
> +           bp = bitpack_create (ob->main_stream);
> +           bp_pack_value (&bp, info->inlinable, 1);
> +           streamer_write_bitpack (&bp);
> +           streamer_write_uhwi (ob, VEC_length (condition, info->conds));
> +           for (i = 0; VEC_iterate (condition, info->conds, i, c); i++)
> +             {
> +               streamer_write_uhwi (ob, c->operand_num);
> +               streamer_write_uhwi (ob, c->code);
> +               stream_write_tree (ob, c->val, true);
> +               bp = bitpack_create (ob->main_stream);
> +               bp_pack_value (&bp, c->agg_contents, 1);
> +               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, VEC_length (size_time_entry, info->entry));
> +           for (i = 0;
> +                VEC_iterate (size_time_entry, info->entry, i, e);
> +                i++)
> +             {
> +               streamer_write_uhwi (ob, e->size);
> +               streamer_write_uhwi (ob, e->time);
> +               write_predicate (ob, &e->predicate);
> +             }
> +           write_predicate (ob, info->loop_iterations);
> +           write_predicate (ob, info->loop_stride);
> +           for (edge = node->callees; edge; edge = edge->next_callee)
> +             write_inline_edge_summary (ob, edge);
> +           for (edge = node->indirect_calls; edge; edge = edge->next_callee)
> +             write_inline_edge_summary (ob, edge);
>         }
>      }
>    streamer_write_char_stream (ob->main_stream, 0);
> Index: gcc/lto/lto.c
> ===================================================================
> --- gcc/lto/lto.c       (revision 191403)
> +++ gcc/lto/lto.c       (working copy)
> @@ -2619,12 +2619,16 @@ 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)))
> -                   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)");
> +                 if (cgraph_node *cnode = node->try_function ())
> +                   {
> +                     if (lto_symtab_encoder_encode_body_p (part->encoder, cnode))
> +                     fprintf (cgraph_dump_file, "(body included)");
> +                   }
> +                 else if (varpool_node *vnode = node->try_variable ())
> +                   {
> +                     if (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 191403)
> +++ 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)
> -    return SYMBOL_DUPLICATE;
> +  if (cgraph_node *cnode = node->try_function ())
> +    if (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 191403)
> +++ 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_tree (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_tree (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 191403)
> +++ gcc/symtab.c        (working copy)
> @@ -239,8 +239,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
> @@ -281,10 +281,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);
>  }
>
>  /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
> @@ -514,10 +514,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.  */
> @@ -555,7 +555,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)
>         {
> @@ -563,7 +563,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)
>         {
> @@ -651,8 +651,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 191403)
> +++ 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_tree (decl);
>  }
>
>  /* Called after finishing a record, union or enumeral type.  */
> Index: gcc/varpool.c
> ===================================================================
> --- gcc/varpool.c       (revision 191403)
> +++ 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_tree (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_tree (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_tree (node->alias_of);
>        struct varpool_node *n;
>
>        for (n = tgt; n && n->alias;
> @@ -374,16 +374,15 @@ 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);
> +           if (varpool_node *vnext = next->try_variable ())
> +             if (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);
> +       if (varpool_node *vnode = ref->referred->try_variable ())
> +         if ((!DECL_EXTERNAL (ref->referred->symbol.decl) || vnode->alias)
> +             && vnode->analyzed)
> +           enqueue_node (vnode, &first);
>      }
>    if (cgraph_dump_file)
>      fprintf (cgraph_dump_file, "\nRemoving variables:");
> @@ -457,7 +456,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_tree (new_decl);
>    varpool_finalize_decl (new_decl);
>
>    return new_node->symbol.decl;
> @@ -473,7 +472,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_tree (alias);
>    alias_node->alias = 1;
>    alias_node->finalized = 1;
>    alias_node->alias_of = decl;
> Index: gcc/lto-streamer.h
> ===================================================================
> --- gcc/lto-streamer.h  (revision 191403)
> +++ gcc/lto-streamer.h  (working copy)
> @@ -1121,7 +1121,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);
>  }
> @@ -1134,7 +1134,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);
>
> @@ -1147,7 +1147,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);
>  }
> @@ -1160,7 +1160,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

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

* Re: Use conditional casting with symtab_node
  2012-09-18 19:57 ` Richard Guenther
@ 2012-09-18 20:32   ` Lawrence Crowl
  0 siblings, 0 replies; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-18 20:32 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches List, Jan Hubicka, Diego Novillo

On 9/18/12, Richard Guenther <richard.guenther@gmail.com> wrote:
> On Sep 18, 2012 Lawrence Crowl <crowl@googlers.com> wrote:
> > * cgraph.h (varpool_node): Rename to varpool_node_for_tree.
>
> Sure it should be varpool_node_for_decl, if any.
> Or varpool_node_from_decl (grep for what is more common)

Grep says _for_decl wins over _from_decl by 113 to 74.
I will make that change unless I hear an objection soon.

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-09-18 18:37   ` Lawrence Crowl
@ 2012-09-19  7:31     ` Eric Botcazou
  2012-09-19  9:17       ` Richard Guenther
  2012-09-19 18:39       ` Lawrence Crowl
  0 siblings, 2 replies; 47+ messages in thread
From: Eric Botcazou @ 2012-09-19  7:31 UTC (permalink / raw)
  To: Lawrence Crowl; +Cc: gcc-patches, Jan Hubicka, Diego Novillo

> 
> The language syntax would bind the conditional into the intializer, as in
> 
>   if (varpool_node *vnode = (node->try_variable ()
>                              && vnode->finalized))
>     varpool_analyze_node (vnode);
> 
> which does not type-match.
> 
> So, if you want the type saftey and performance, the cascade is really
> unavoidable.

Just write:

  varpool_node *vnode;

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

This has been the standard style for the past 2 decades and trading it for 
cascading if's is really a bad idea.

-- 
Eric Botcazou

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

* Re: Use conditional casting with symtab_node
  2012-09-19  7:31     ` Eric Botcazou
@ 2012-09-19  9:17       ` Richard Guenther
  2012-09-19 12:19         ` Gabriel Dos Reis
                           ` (2 more replies)
  2012-09-19 18:39       ` Lawrence Crowl
  1 sibling, 3 replies; 47+ messages in thread
From: Richard Guenther @ 2012-09-19  9:17 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: Lawrence Crowl, gcc-patches, Jan Hubicka, Diego Novillo

On Wed, Sep 19, 2012 at 9:29 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>>
>> The language syntax would bind the conditional into the intializer, as in
>>
>>   if (varpool_node *vnode = (node->try_variable ()
>>                              && vnode->finalized))
>>     varpool_analyze_node (vnode);
>>
>> which does not type-match.
>>
>> So, if you want the type saftey and performance, the cascade is really
>> unavoidable.
>
> Just write:
>
>   varpool_node *vnode;
>
>   if ((vnode = node->try_variable ()) && vnode->finalized)
>     varpool_analyze_node (vnode);
>
> This has been the standard style for the past 2 decades and trading it for
> cascading if's is really a bad idea.

Indeed.  Btw, can we not provide a specialization for dynamic_cast <>?
This ->try_... looks awkward to me compared to the more familiar

  vnode = dynamic_cast <varpool_node> (node)

but yeah - dynamic_cast is not a template ... (but maybe there is some
standard library piece that mimics it?).

Richard.

> --
> Eric Botcazou

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

* Re: Use conditional casting with symtab_node
  2012-09-19  9:17       ` Richard Guenther
@ 2012-09-19 12:19         ` Gabriel Dos Reis
  2012-09-19 19:04           ` Lawrence Crowl
  2012-09-20 13:25         ` Michael Matz
  2012-10-11  5:22         ` Xinliang David Li
  2 siblings, 1 reply; 47+ messages in thread
From: Gabriel Dos Reis @ 2012-09-19 12:19 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Eric Botcazou, Lawrence Crowl, gcc-patches, Jan Hubicka, Diego Novillo

On Wed, Sep 19, 2012 at 4:17 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Sep 19, 2012 at 9:29 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>>>
>>> The language syntax would bind the conditional into the intializer, as in
>>>
>>>   if (varpool_node *vnode = (node->try_variable ()
>>>                              && vnode->finalized))
>>>     varpool_analyze_node (vnode);
>>>
>>> which does not type-match.
>>>
>>> So, if you want the type saftey and performance, the cascade is really
>>> unavoidable.
>>
>> Just write:
>>
>>   varpool_node *vnode;
>>
>>   if ((vnode = node->try_variable ()) && vnode->finalized)
>>     varpool_analyze_node (vnode);
>>
>> This has been the standard style for the past 2 decades and trading it for
>> cascading if's is really a bad idea.
>
> Indeed.  Btw, can we not provide a specialization for dynamic_cast <>?

No, it is a language primitive.

but we can define out own operation with similar syntax that allows
for specialization, whose generic implementation uses dynamic_cast.

   template<typename T, typename U>
   T* is(U* u) {
       return dynamic_cast<T*>(u);
    }

> This ->try_... looks awkward to me compared to the more familiar
>
>   vnode = dynamic_cast <varpool_node> (node)
>
> but yeah - dynamic_cast is not a template ... (but maybe there is some
> standard library piece that mimics it?).



>
> Richard.
>
>> --
>> Eric Botcazou

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

* Re: Use conditional casting with symtab_node
  2012-09-19  7:31     ` Eric Botcazou
  2012-09-19  9:17       ` Richard Guenther
@ 2012-09-19 18:39       ` Lawrence Crowl
  2012-09-20 13:26         ` Michael Matz
  1 sibling, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-19 18:39 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, Jan Hubicka, Diego Novillo

On 9/19/12, Eric Botcazou <ebotcazou@adacore.com> wrote:
> > The language syntax would bind the conditional into the
> > intializer, as in
> >
> >   if (varpool_node *vnode = (node->try_variable ()
> >                              && vnode->finalized))
> >     varpool_analyze_node (vnode);
> >
> > which does not type-match.
> >
> > So, if you want the type saftey and performance, the cascade
> > is really unavoidable.
>
> Just write:
>
>   varpool_node *vnode;
>
>   if ((vnode = node->try_variable ()) && vnode->finalized)
>     varpool_analyze_node (vnode);
>
> This has been the standard style for the past 2 decades and
> trading it for cascading if's is really a bad idea.

Assignments in if statements are known to cause confusion.

The point of the change is to limit the scope of the variable
to the if statement, which prevents its unintended use later.
It acts like a type switch.

Why do you think cascading ifs is a bad idea?

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-09-19 12:19         ` Gabriel Dos Reis
@ 2012-09-19 19:04           ` Lawrence Crowl
  2012-09-19 21:28             ` Gabriel Dos Reis
  2012-10-11  5:31             ` Xinliang David Li
  0 siblings, 2 replies; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-19 19:04 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: Richard Guenther, Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On 9/19/12, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
> On Sep 19, 2012 Richard Guenther <richard.guenther@gmail.com> wrote:
> > Indeed.  Btw, can we not provide a specialization for
> > dynamic_cast <>?  This ->try_... looks awkward to me compared
> > to the more familiar
> >
> > vnode = dynamic_cast <varpool_node> (node)
> >
> > but yeah - dynamic_cast is not a template ... (but maybe there
> > is some standard library piece that mimics it?).
>
> No, it is a language primitive.
>
> but we can define out own operation with similar syntax that allows
> for specialization, whose generic implementation uses dynamic_cast.
>
>   template<typename T, typename U>
>   T* is(U* u) {
>       return dynamic_cast<T*>(u);
>   }

At this point, dynamic_cast is not available because we do not
yet have polymorphic types.  There has been some resistance to
that notion.

Absent dynamic cast, we need to specialize for various type
combinations.  Function template specialization would be handy,
but C++ does not directly support that.  We could work around
that.  However, in the end, the fact that try_whatever is a member
function means that we can use a notation that depends on context
and so can be shorter.  That is, we can write 'function' instead of
'cgraph_node *'.

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-09-19 19:04           ` Lawrence Crowl
@ 2012-09-19 21:28             ` Gabriel Dos Reis
  2012-09-19 22:03               ` Lawrence Crowl
  2012-10-11  5:31             ` Xinliang David Li
  1 sibling, 1 reply; 47+ messages in thread
From: Gabriel Dos Reis @ 2012-09-19 21:28 UTC (permalink / raw)
  To: Lawrence Crowl
  Cc: Richard Guenther, Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On Wed, Sep 19, 2012 at 1:39 PM, Lawrence Crowl <crowl@googlers.com> wrote:
> On 9/19/12, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>> On Sep 19, 2012 Richard Guenther <richard.guenther@gmail.com> wrote:
>> > Indeed.  Btw, can we not provide a specialization for
>> > dynamic_cast <>?  This ->try_... looks awkward to me compared
>> > to the more familiar
>> >
>> > vnode = dynamic_cast <varpool_node> (node)
>> >
>> > but yeah - dynamic_cast is not a template ... (but maybe there
>> > is some standard library piece that mimics it?).
>>
>> No, it is a language primitive.
>>
>> but we can define out own operation with similar syntax that allows
>> for specialization, whose generic implementation uses dynamic_cast.
>>
>>   template<typename T, typename U>
>>   T* is(U* u) {
>>       return dynamic_cast<T*>(u);
>>   }
>
> At this point, dynamic_cast is not available because we do not
> yet have polymorphic types.  There has been some resistance to
> that notion.

Hmm, when did we rule that out?

We currently implement dynamic_cast using the poor man's simulation
based on tree_code checking.  We can just as well give such
simulation the is<> notation.

> Absent dynamic cast, we need to specialize for various type
> combinations.  Function template specialization would be handy,
> but C++ does not directly support that.  We could work around
> that.

We can always use the standard workaround: call a static member
function of a class template that can be specialized at will.

> However, in the end, the fact that try_whatever is a member
> function means that we can use a notation that depends on context
> and so can be shorter.  That is, we can write 'function' instead of
> 'cgraph_node *'.
>
> --
> Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-09-19 21:28             ` Gabriel Dos Reis
@ 2012-09-19 22:03               ` Lawrence Crowl
  0 siblings, 0 replies; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-19 22:03 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: Richard Guenther, Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On 9/19/12, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
> On Wed, Sep 19, 2012 at 1:39 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>> On 9/19/12, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>>> On Sep 19, 2012 Richard Guenther <richard.guenther@gmail.com> wrote:
>>> > Indeed.  Btw, can we not provide a specialization for
>>> > dynamic_cast <>?  This ->try_... looks awkward to me compared
>>> > to the more familiar
>>> >
>>> > vnode = dynamic_cast <varpool_node> (node)
>>> >
>>> > but yeah - dynamic_cast is not a template ... (but maybe there
>>> > is some standard library piece that mimics it?).
>>>
>>> No, it is a language primitive.
>>>
>>> but we can define out own operation with similar syntax that allows
>>> for specialization, whose generic implementation uses dynamic_cast.
>>>
>>>   template<typename T, typename U>
>>>   T* is(U* u) {
>>>       return dynamic_cast<T*>(u);
>>>   }
>>
>> At this point, dynamic_cast is not available because we do not
>> yet have polymorphic types.  There has been some resistance to
>> that notion.
>
> Hmm, when did we rule that out?

We have not ruled it out, but folks are, rightly, concerned about any
size increase in critical data structures.  We are also currently
lacking a gengtype that will handle inheritance.  So, for now at
least, we need a scheme that will work across both inheritance and
our current tag/union approach.

> We currently implement dynamic_cast using the poor man's simulation
> based on tree_code checking.  We can just as well give such
> simulation the is<> notation.
>
>> Absent dynamic cast, we need to specialize for various type
>> combinations.  Function template specialization would be handy,
>> but C++ does not directly support that.  We could work around
>> that.
>
> We can always use the standard workaround: call a static member
> function of a class template that can be specialized at will.
>
>> However, in the end, the fact that try_whatever is a member
>> function means that we can use a notation that depends on context
>> and so can be shorter.  That is, we can write 'function' instead of
>> 'cgraph_node *'.

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-09-19  9:17       ` Richard Guenther
  2012-09-19 12:19         ` Gabriel Dos Reis
@ 2012-09-20 13:25         ` Michael Matz
  2012-10-11  5:22         ` Xinliang David Li
  2 siblings, 0 replies; 47+ messages in thread
From: Michael Matz @ 2012-09-20 13:25 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Eric Botcazou, Lawrence Crowl, gcc-patches, Jan Hubicka, Diego Novillo

Hi,

On Wed, 19 Sep 2012, Richard Guenther wrote:

> > Just write:
> >
> >   varpool_node *vnode;
> >
> >   if ((vnode = node->try_variable ()) && vnode->finalized)
> >     varpool_analyze_node (vnode);
> >
> > This has been the standard style for the past 2 decades and trading it for
> > cascading if's is really a bad idea.
> 
> Indeed.  Btw, can we not provide a specialization for dynamic_cast <>?
> This ->try_... looks awkward to me compared to the more familiar
> 
>   vnode = dynamic_cast <varpool_node> (node)

Gah.  The less '<>' characters in source code the better.  I'm not 
thrilled, but prefer the ->try_ thingy.  And yes, cascading if's for this 
idiom is bad.


Ciao,
Michael.

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

* Re: Use conditional casting with symtab_node
  2012-09-19 18:39       ` Lawrence Crowl
@ 2012-09-20 13:26         ` Michael Matz
  2012-09-20 20:01           ` Lawrence Crowl
  0 siblings, 1 reply; 47+ messages in thread
From: Michael Matz @ 2012-09-20 13:26 UTC (permalink / raw)
  To: Lawrence Crowl; +Cc: Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

Hi,

On Wed, 19 Sep 2012, Lawrence Crowl wrote:

> On 9/19/12, Eric Botcazou <ebotcazou@adacore.com> wrote:
> > > The language syntax would bind the conditional into the
> > > intializer, as in
> > >
> > >   if (varpool_node *vnode = (node->try_variable ()
> > >                              && vnode->finalized))
> > >     varpool_analyze_node (vnode);
> > >
> > > which does not type-match.
> > >
> > > So, if you want the type saftey and performance, the cascade
> > > is really unavoidable.
> >
> > Just write:
> >
> >   varpool_node *vnode;
> >
> >   if ((vnode = node->try_variable ()) && vnode->finalized)
> >     varpool_analyze_node (vnode);
> >
> > This has been the standard style for the past 2 decades and
> > trading it for cascading if's is really a bad idea.
> 
> Assignments in if statements are known to cause confusion.

So?  Make it:

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

> The point of the change is to limit the scope of the variable
> to the if statement, which prevents its unintended use later.

I'm not worried about this.

> Why do you think cascading ifs is a bad idea?

Precedent.  Confusion in case of dangling else (requiring more {}, and 
hence even more indentation).  Ugly.


Ciao,
Michael.

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

* Re: Use conditional casting with symtab_node
  2012-09-20 13:26         ` Michael Matz
@ 2012-09-20 20:01           ` Lawrence Crowl
  2012-09-20 22:02             ` Gabriel Dos Reis
  0 siblings, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-20 20:01 UTC (permalink / raw)
  To: Michael Matz; +Cc: Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On 9/20/12, Michael Matz <matz@suse.de> wrote:
> On Wed, 19 Sep 2012, Lawrence Crowl wrote:
> > On 9/19/12, Eric Botcazou <ebotcazou@adacore.com> wrote:
> > > > The language syntax would bind the conditional into the
> > > > intializer, as in
> > > >
> > > >   if (varpool_node *vnode = (node->try_variable ()
> > > >                              && vnode->finalized))
> > > >     varpool_analyze_node (vnode);
> > > >
> > > > which does not type-match.
> > > >
> > > > So, if you want the type saftey and performance, the cascade
> > > > is really unavoidable.
> > >
> > > Just write:
> > >
> > >   varpool_node *vnode;
> > >
> > >   if ((vnode = node->try_variable ()) && vnode->finalized)
> > >     varpool_analyze_node (vnode);
> > >
> > > This has been the standard style for the past 2 decades and
> > > trading it for cascading if's is really a bad idea.
> >
> > Assignments in if statements are known to cause confusion.
>
> So?  Make it:
>
>   varpool_node *vnode = node->try_variable ();
>   if (vnode && vnode->finalized)
>     varpool_analyze_node (vnode);
>
> > The point of the change is to limit the scope of the variable
> > to the if statement, which prevents its unintended use later.
>
> I'm not worried about this.

It is helpful to have the language and the usage in concurrence.

Okay, so unless someone objects, I'll move the variable out when
it introduces a cacade.

> > Why do you think cascading ifs is a bad idea?
>
> Precedent.  Confusion in case of dangling else (requiring more {},
> and hence even more indentation).  Ugly.

I generally take ugly as an indication that the function needs
refactoring.

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-09-20 20:01           ` Lawrence Crowl
@ 2012-09-20 22:02             ` Gabriel Dos Reis
  2012-09-20 22:06               ` Lawrence Crowl
  0 siblings, 1 reply; 47+ messages in thread
From: Gabriel Dos Reis @ 2012-09-20 22:02 UTC (permalink / raw)
  To: Lawrence Crowl
  Cc: Michael Matz, Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On Thu, Sep 20, 2012 at 1:53 PM, Lawrence Crowl <crowl@googlers.com> wrote:

>> > Why do you think cascading ifs is a bad idea?
>>
>> Precedent.  Confusion in case of dangling else (requiring more {},
>> and hence even more indentation).  Ugly.
>
> I generally take ugly as an indication that the function needs
> refactoring.

Hear!  Hear! Hear!

Sadly, many functions in GCC (at least in cp/) are in that category :-(

-- Gaby

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

* Re: Use conditional casting with symtab_node
  2012-09-20 22:02             ` Gabriel Dos Reis
@ 2012-09-20 22:06               ` Lawrence Crowl
  0 siblings, 0 replies; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-20 22:06 UTC (permalink / raw)
  To: Gabriel Dos Reis
  Cc: Michael Matz, Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On 9/20/12, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
> On Sep 20, 2012 Lawrence Crowl <crowl@googlers.com> wrote:
> > > > Why do you think cascading ifs is a bad idea?
> > >
> > > Precedent.  Confusion in case of dangling else (requiring
> > > more {}, and hence even more indentation).  Ugly.
> >
> > I generally take ugly as an indication that the function needs
> > refactoring.
>
> Hear!  Hear! Hear!
>
> Sadly, many functions in GCC (at least in cp/) are in that
> category :-(

It is not just GCC.  Most large codebases I've seen have had lots of
large functions.  It takes persistent effort to beat back entropy.

I once chatted with a guy who worked on a project with a strict
requirement that every function fit on one screen, and that was
when screens were 24 lines.  He said their bug rate was really low.
And the one function they made an exception for turned out the have
the worst bug in it.

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-09-18 18:02 Use conditional casting with symtab_node Lawrence Crowl
  2012-09-18 18:09 ` Eric Botcazou
  2012-09-18 19:57 ` Richard Guenther
@ 2012-09-22  6:07 ` Lawrence Crowl
  2012-09-25 21:25   ` Lawrence Crowl
  2012-10-03  0:32   ` Lawrence Crowl
  2 siblings, 2 replies; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-22  6:07 UTC (permalink / raw)
  To: gcc-patches List, Jan Hubicka; +Cc: Diego Novillo

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 inappropritately.)

  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_tree.


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


Tested on x86_64.


Okay for trunk?



Index: gcc/ChangeLog

2012-09-18  Lawrence Crowl  <crowl@google.com

	* cgraph.h (varpool_node): Rename to varpool_node_for_tree.
	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.
	* graphunit.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 191403)
+++ gcc/lto-symtab.c	(working copy)
@@ -743,7 +743,7 @@ lto_symtab_merge_cgraph_nodes_1 (void **
 	{
 	  if (!prevailing->vnode)
 	    {
-	      prevailing->vnode = varpool_node (prevailing->decl);
+	      prevailing->vnode = varpool_node_for_tree (prevailing->decl);
 	      prevailing->vnode->alias = true;
 	    }
 	  lto_varpool_replace_node (e->vnode, prevailing->vnode);
Index: gcc/cgraphbuild.c
===================================================================
--- gcc/cgraphbuild.c	(revision 191403)
+++ 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_tree (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_tree (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_tree (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_tree (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_tree (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_tree (decl);
   struct record_reference_ctx ctx = {false, NULL};

   ctx.varpool_node = node;
Index: gcc/cgraph.c
===================================================================
--- gcc/cgraph.c	(revision 191403)
+++ gcc/cgraph.c	(working copy)
@@ -506,9 +506,12 @@ 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 (; 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 191403)
+++ gcc/cgraph.h	(working copy)
@@ -448,13 +448,46 @@ 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;
 };

+inline bool
+symtab_node_def::is_function ()
+{
+  return symbol.type == SYMTAB_FUNCTION;
+}
+
+inline bool
+symtab_node_def::is_variable ()
+{
+  return symbol.type == SYMTAB_VARIABLE;
+}
+
+inline cgraph_node *
+symtab_node_def::try_function ()
+{
+  return is_function () ? &x_function : 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;
@@ -677,7 +710,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_tree (tree);
 struct varpool_node *varpool_node_for_asm (tree asmname);
 void varpool_mark_needed_node (struct varpool_node *);
 void debug_varpool (void);
@@ -705,19 +738,6 @@ bool varpool_for_node_and_aliases (struc
 			           void *, bool);
 void varpool_add_new_variable (tree);

-/* 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 *
@@ -790,10 +810,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;
 }

@@ -803,10 +821,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.  */
@@ -822,9 +838,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;
 }
@@ -836,9 +852,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;
 }
@@ -855,8 +871,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;
 }
@@ -868,8 +885,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;
 }
@@ -885,8 +903,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;
 }
@@ -898,8 +917,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;
 }
@@ -915,10 +935,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;
 }

@@ -928,10 +946,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.  */
@@ -958,9 +974,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;
 }
@@ -972,9 +988,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;
 }
@@ -1173,7 +1189,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;
 }
@@ -1187,7 +1203,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;
 }
Index: gcc/tree-emutls.c
===================================================================
--- gcc/tree-emutls.c	(revision 191403)
+++ 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_tree (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_tree (to);
   else if (!alias_of)
     varpool_add_new_variable (to);
   else
Index: gcc/ipa-reference.c
===================================================================
--- gcc/ipa-reference.c	(revision 191403)
+++ 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,18 +992,16 @@ 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;
 	  bitmap_set_bit (ltrans_statics, DECL_UID (decl));
 	  splay_tree_insert (reference_vars_to_consider,
-			     DECL_UID (decl), (splay_tree_value)decl);
+			 DECL_UID (decl), (splay_tree_value)decl);
 	  ltrans_statics_bitcount ++;
 	}
     }
@@ -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 191403)
+++ gcc/cgraphunit.c	(working copy)
@@ -388,7 +388,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;
 }
@@ -818,7 +819,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_tree (decl);

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

@@ -845,6 +846,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  */

@@ -879,13 +909,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)
@@ -912,18 +936,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)
@@ -938,23 +959,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)
 	    {
@@ -965,8 +988,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 ();
 	}
@@ -994,10 +1016,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)
@@ -1079,7 +1100,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)
@@ -1088,7 +1109,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 191403)
+++ gcc/cp/decl2.c	(working copy)
@@ -1773,7 +1773,7 @@ import_export_class (tree ctype)
 static bool
 var_finalized_p (tree var)
 {
-  return varpool_node (var)->finalized;
+  return varpool_node_for_tree (var)->finalized;
 }

 /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
@@ -1891,7 +1891,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_tree (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 191403)
+++ 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 191403)
+++ 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
       {
@@ -719,9 +719,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)
@@ -785,8 +784,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);
 	
@@ -972,7 +971,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_tree (var_decl);
   node->symbol.order = order;
   if (order >= symtab_order)
     symtab_order = order + 1;
@@ -1133,14 +1132,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)
@@ -1149,9 +1148,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;
@@ -1163,7 +1162,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;
 }

@@ -1437,7 +1436,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);
@@ -1447,18 +1445,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 191403)
+++ gcc/lto-streamer-out.c	(working copy)
@@ -975,7 +975,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 ();
@@ -991,10 +990,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)
 	{
@@ -1288,8 +1286,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;
@@ -1305,49 +1301,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
@@ -1359,9 +1358,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 191403)
+++ 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_tree (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 191403)
+++ 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 191403)
+++ gcc/ipa-inline-analysis.c	(working copy)
@@ -3816,22 +3816,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;
@@ -3839,7 +3842,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);
@@ -3858,7 +3861,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 191403)
+++ gcc/lto/lto.c	(working copy)
@@ -2619,12 +2619,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 191403)
+++ 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 191403)
+++ 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_tree (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_tree (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 191403)
+++ gcc/symtab.c	(working copy)
@@ -239,8 +239,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
@@ -281,10 +281,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);
 }

 /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
@@ -514,10 +514,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.  */
@@ -555,7 +555,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)
 	{
@@ -563,7 +563,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)
 	{
@@ -651,8 +651,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 191403)
+++ 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_tree (decl);
 }

 /* Called after finishing a record, union or enumeral type.  */
Index: gcc/varpool.c
===================================================================
--- gcc/varpool.c	(revision 191403)
+++ 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_tree (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_tree (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_tree (node->alias_of);
       struct varpool_node *n;

       for (n = tgt; n && n->alias;
@@ -374,16 +374,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:");
@@ -457,7 +462,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_tree (new_decl);
   varpool_finalize_decl (new_decl);

   return new_node->symbol.decl;
@@ -473,7 +478,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_tree (alias);
   alias_node->alias = 1;
   alias_node->finalized = 1;
   alias_node->alias_of = decl;
Index: gcc/lto-streamer.h
===================================================================
--- gcc/lto-streamer.h	(revision 191403)
+++ gcc/lto-streamer.h	(working copy)
@@ -1121,7 +1121,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);
 }
@@ -1134,7 +1134,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);

@@ -1147,7 +1147,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);
 }
@@ -1160,7 +1160,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

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

* Re: Use conditional casting with symtab_node
  2012-09-22  6:07 ` Lawrence Crowl
@ 2012-09-25 21:25   ` Lawrence Crowl
  2012-10-03  0:32   ` Lawrence Crowl
  1 sibling, 0 replies; 47+ messages in thread
From: Lawrence Crowl @ 2012-09-25 21:25 UTC (permalink / raw)
  To: gcc-patches List, Jan Hubicka; +Cc: Diego Novillo

Ping!

On 9/21/12, Lawrence Crowl <crowl@googlers.com> wrote:
> 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 inappropritately.)
>
>   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_tree.
>
>
> The new code bootstraps .616% faster with a 99% confidence of being faster.
>
>
> Tested on x86_64.
>
>
> Okay for trunk?
>
>
>
> Index: gcc/ChangeLog
>
> 2012-09-18  Lawrence Crowl  <crowl@google.com
>
> 	* cgraph.h (varpool_node): Rename to varpool_node_for_tree.
> 	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.
> 	* graphunit.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 191403)
> +++ gcc/lto-symtab.c	(working copy)
> @@ -743,7 +743,7 @@ lto_symtab_merge_cgraph_nodes_1 (void **
>  	{
>  	  if (!prevailing->vnode)
>  	    {
> -	      prevailing->vnode = varpool_node (prevailing->decl);
> +	      prevailing->vnode = varpool_node_for_tree (prevailing->decl);
>  	      prevailing->vnode->alias = true;
>  	    }
>  	  lto_varpool_replace_node (e->vnode, prevailing->vnode);
> Index: gcc/cgraphbuild.c
> ===================================================================
> --- gcc/cgraphbuild.c	(revision 191403)
> +++ 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_tree (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_tree (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_tree (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_tree (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_tree (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_tree (decl);
>    struct record_reference_ctx ctx = {false, NULL};
>
>    ctx.varpool_node = node;
> Index: gcc/cgraph.c
> ===================================================================
> --- gcc/cgraph.c	(revision 191403)
> +++ gcc/cgraph.c	(working copy)
> @@ -506,9 +506,12 @@ 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 (; 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 191403)
> +++ gcc/cgraph.h	(working copy)
> @@ -448,13 +448,46 @@ 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;
>  };
>
> +inline bool
> +symtab_node_def::is_function ()
> +{
> +  return symbol.type == SYMTAB_FUNCTION;
> +}
> +
> +inline bool
> +symtab_node_def::is_variable ()
> +{
> +  return symbol.type == SYMTAB_VARIABLE;
> +}
> +
> +inline cgraph_node *
> +symtab_node_def::try_function ()
> +{
> +  return is_function () ? &x_function : 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;
> @@ -677,7 +710,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_tree (tree);
>  struct varpool_node *varpool_node_for_asm (tree asmname);
>  void varpool_mark_needed_node (struct varpool_node *);
>  void debug_varpool (void);
> @@ -705,19 +738,6 @@ bool varpool_for_node_and_aliases (struc
>  			           void *, bool);
>  void varpool_add_new_variable (tree);
>
> -/* 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 *
> @@ -790,10 +810,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;
>  }
>
> @@ -803,10 +821,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.  */
> @@ -822,9 +838,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;
>  }
> @@ -836,9 +852,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;
>  }
> @@ -855,8 +871,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;
>  }
> @@ -868,8 +885,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;
>  }
> @@ -885,8 +903,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;
>  }
> @@ -898,8 +917,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;
>  }
> @@ -915,10 +935,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;
>  }
>
> @@ -928,10 +946,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.  */
> @@ -958,9 +974,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;
>  }
> @@ -972,9 +988,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;
>  }
> @@ -1173,7 +1189,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;
>  }
> @@ -1187,7 +1203,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;
>  }
> Index: gcc/tree-emutls.c
> ===================================================================
> --- gcc/tree-emutls.c	(revision 191403)
> +++ 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_tree (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_tree (to);
>    else if (!alias_of)
>      varpool_add_new_variable (to);
>    else
> Index: gcc/ipa-reference.c
> ===================================================================
> --- gcc/ipa-reference.c	(revision 191403)
> +++ 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,18 +992,16 @@ 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;
>  	  bitmap_set_bit (ltrans_statics, DECL_UID (decl));
>  	  splay_tree_insert (reference_vars_to_consider,
> -			     DECL_UID (decl), (splay_tree_value)decl);
> +			 DECL_UID (decl), (splay_tree_value)decl);
>  	  ltrans_statics_bitcount ++;
>  	}
>      }
> @@ -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 191403)
> +++ gcc/cgraphunit.c	(working copy)
> @@ -388,7 +388,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;
>  }
> @@ -818,7 +819,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_tree (decl);
>
>    gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
>
> @@ -845,6 +846,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  */
>
> @@ -879,13 +909,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)
> @@ -912,18 +936,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)
> @@ -938,23 +959,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)
>  	    {
> @@ -965,8 +988,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 ();
>  	}
> @@ -994,10 +1016,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)
> @@ -1079,7 +1100,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)
> @@ -1088,7 +1109,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 191403)
> +++ gcc/cp/decl2.c	(working copy)
> @@ -1773,7 +1773,7 @@ import_export_class (tree ctype)
>  static bool
>  var_finalized_p (tree var)
>  {
> -  return varpool_node (var)->finalized;
> +  return varpool_node_for_tree (var)->finalized;
>  }
>
>  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
> @@ -1891,7 +1891,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_tree (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 191403)
> +++ 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 191403)
> +++ 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
>        {
> @@ -719,9 +719,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)
> @@ -785,8 +784,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);
>  	
> @@ -972,7 +971,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_tree (var_decl);
>    node->symbol.order = order;
>    if (order >= symtab_order)
>      symtab_order = order + 1;
> @@ -1133,14 +1132,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)
> @@ -1149,9 +1148,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;
> @@ -1163,7 +1162,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;
>  }
>
> @@ -1437,7 +1436,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);
> @@ -1447,18 +1445,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 191403)
> +++ gcc/lto-streamer-out.c	(working copy)
> @@ -975,7 +975,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 ();
> @@ -991,10 +990,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)
>  	{
> @@ -1288,8 +1286,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;
> @@ -1305,49 +1301,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
> @@ -1359,9 +1358,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 191403)
> +++ 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_tree (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 191403)
> +++ 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 191403)
> +++ gcc/ipa-inline-analysis.c	(working copy)
> @@ -3816,22 +3816,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;
> @@ -3839,7 +3842,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);
> @@ -3858,7 +3861,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 191403)
> +++ gcc/lto/lto.c	(working copy)
> @@ -2619,12 +2619,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 191403)
> +++ 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 191403)
> +++ 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_tree (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_tree (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 191403)
> +++ gcc/symtab.c	(working copy)
> @@ -239,8 +239,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
> @@ -281,10 +281,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);
>  }
>
>  /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
> @@ -514,10 +514,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.  */
> @@ -555,7 +555,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)
>  	{
> @@ -563,7 +563,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)
>  	{
> @@ -651,8 +651,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 191403)
> +++ 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_tree (decl);
>  }
>
>  /* Called after finishing a record, union or enumeral type.  */
> Index: gcc/varpool.c
> ===================================================================
> --- gcc/varpool.c	(revision 191403)
> +++ 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_tree (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_tree (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_tree (node->alias_of);
>        struct varpool_node *n;
>
>        for (n = tgt; n && n->alias;
> @@ -374,16 +374,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:");
> @@ -457,7 +462,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_tree (new_decl);
>    varpool_finalize_decl (new_decl);
>
>    return new_node->symbol.decl;
> @@ -473,7 +478,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_tree (alias);
>    alias_node->alias = 1;
>    alias_node->finalized = 1;
>    alias_node->alias_of = decl;
> Index: gcc/lto-streamer.h
> ===================================================================
> --- gcc/lto-streamer.h	(revision 191403)
> +++ gcc/lto-streamer.h	(working copy)
> @@ -1121,7 +1121,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);
>  }
> @@ -1134,7 +1134,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);
>
> @@ -1147,7 +1147,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);
>  }
> @@ -1160,7 +1160,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

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

* Re: Use conditional casting with symtab_node
  2012-09-22  6:07 ` Lawrence Crowl
  2012-09-25 21:25   ` Lawrence Crowl
@ 2012-10-03  0:32   ` Lawrence Crowl
  2012-10-03 12:07     ` Martin Jambor
  1 sibling, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-10-03  0:32 UTC (permalink / raw)
  To: gcc-patches List, Jan Hubicka; +Cc: Diego Novillo

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?


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

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

* Re: Use conditional casting with symtab_node
  2012-10-03  0:32   ` Lawrence Crowl
@ 2012-10-03 12:07     ` Martin Jambor
  2012-10-03 16:53       ` Lawrence Crowl
  0 siblings, 1 reply; 47+ messages in thread
From: Martin Jambor @ 2012-10-03 12:07 UTC (permalink / raw)
  To: Lawrence Crowl; +Cc: gcc-patches List, Jan Hubicka, Diego Novillo

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

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

* Re: Use conditional casting with symtab_node
  2012-10-03 12:07     ` Martin Jambor
@ 2012-10-03 16:53       ` Lawrence Crowl
  2012-10-04  8:00         ` Richard Guenther
  0 siblings, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-10-03 16:53 UTC (permalink / raw)
  To: Lawrence Crowl, gcc-patches List, Jan Hubicka, Diego Novillo

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
>


-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-03 16:53       ` Lawrence Crowl
@ 2012-10-04  8:00         ` Richard Guenther
  2012-10-04 18:14           ` Lawrence Crowl
  0 siblings, 1 reply; 47+ messages in thread
From: Richard Guenther @ 2012-10-04  8:00 UTC (permalink / raw)
  To: Lawrence Crowl; +Cc: gcc-patches List, Jan Hubicka, Diego Novillo

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

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

* Re: Use conditional casting with symtab_node
  2012-10-04  8:00         ` Richard Guenther
@ 2012-10-04 18:14           ` Lawrence Crowl
  2012-10-04 18:17             ` Diego Novillo
  0 siblings, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-10-04 18:14 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches List, Jan Hubicka, Diego Novillo

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
>


-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-04 18:14           ` Lawrence Crowl
@ 2012-10-04 18:17             ` Diego Novillo
  2012-10-05  8:50               ` Richard Guenther
  0 siblings, 1 reply; 47+ messages in thread
From: Diego Novillo @ 2012-10-04 18:17 UTC (permalink / raw)
  To: Lawrence Crowl; +Cc: Richard Guenther, gcc-patches List, Jan Hubicka

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.

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

* Re: Use conditional casting with symtab_node
  2012-10-04 18:17             ` Diego Novillo
@ 2012-10-05  8:50               ` Richard Guenther
  2012-10-05  9:52                 ` Jan Hubicka
                                   ` (2 more replies)
  0 siblings, 3 replies; 47+ messages in thread
From: Richard Guenther @ 2012-10-05  8:50 UTC (permalink / raw)
  To: Diego Novillo; +Cc: Lawrence Crowl, gcc-patches List, Jan Hubicka

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.

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

* Re: Use conditional casting with symtab_node
  2012-10-05  8:50               ` Richard Guenther
@ 2012-10-05  9:52                 ` Jan Hubicka
  2012-10-10  0:58                   ` Lawrence Crowl
  2012-10-05 10:50                 ` Nathan Froyd
  2012-10-11  6:49                 ` Xinliang David Li
  2 siblings, 1 reply; 47+ messages in thread
From: Jan Hubicka @ 2012-10-05  9:52 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Diego Novillo, Lawrence Crowl, gcc-patches List, Jan Hubicka

> 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

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

* Re: Use conditional casting with symtab_node
  2012-10-05  8:50               ` Richard Guenther
  2012-10-05  9:52                 ` Jan Hubicka
@ 2012-10-05 10:50                 ` Nathan Froyd
  2012-10-05 11:05                   ` Richard Guenther
  2012-10-11  6:49                 ` Xinliang David Li
  2 siblings, 1 reply; 47+ messages in thread
From: Nathan Froyd @ 2012-10-05 10:50 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches List

----- 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

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

* Re: Use conditional casting with symtab_node
  2012-10-05 10:50                 ` Nathan Froyd
@ 2012-10-05 11:05                   ` Richard Guenther
  2012-10-05 12:44                     ` Diego Novillo
  0 siblings, 1 reply; 47+ messages in thread
From: Richard Guenther @ 2012-10-05 11:05 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: gcc-patches List

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

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

* Re: Use conditional casting with symtab_node
  2012-10-05 11:05                   ` Richard Guenther
@ 2012-10-05 12:44                     ` Diego Novillo
  2012-10-05 13:58                       ` Steven Bosscher
                                         ` (2 more replies)
  0 siblings, 3 replies; 47+ messages in thread
From: Diego Novillo @ 2012-10-05 12:44 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Nathan Froyd, gcc-patches List

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.

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

* Re: Use conditional casting with symtab_node
  2012-10-05 12:44                     ` Diego Novillo
@ 2012-10-05 13:58                       ` Steven Bosscher
  2012-10-05 14:07                       ` Steven Bosscher
  2012-10-05 21:50                       ` Lawrence Crowl
  2 siblings, 0 replies; 47+ messages in thread
From: Steven Bosscher @ 2012-10-05 13:58 UTC (permalink / raw)
  To: Diego Novillo; +Cc: Richard Guenther, Nathan Froyd, gcc-patches List

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

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

* Re: Use conditional casting with symtab_node
  2012-10-05 12:44                     ` Diego Novillo
  2012-10-05 13:58                       ` Steven Bosscher
@ 2012-10-05 14:07                       ` Steven Bosscher
  2012-10-05 21:50                       ` Lawrence Crowl
  2 siblings, 0 replies; 47+ messages in thread
From: Steven Bosscher @ 2012-10-05 14:07 UTC (permalink / raw)
  To: Diego Novillo; +Cc: Richard Guenther, Nathan Froyd, gcc-patches List

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

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

* Re: Use conditional casting with symtab_node
  2012-10-05 12:44                     ` Diego Novillo
  2012-10-05 13:58                       ` Steven Bosscher
  2012-10-05 14:07                       ` Steven Bosscher
@ 2012-10-05 21:50                       ` Lawrence Crowl
  2012-10-05 22:04                         ` Steven Bosscher
  2 siblings, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-10-05 21:50 UTC (permalink / raw)
  To: Diego Novillo; +Cc: Richard Guenther, Nathan Froyd, gcc-patches List

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.

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-05 21:50                       ` Lawrence Crowl
@ 2012-10-05 22:04                         ` Steven Bosscher
  0 siblings, 0 replies; 47+ messages in thread
From: Steven Bosscher @ 2012-10-05 22:04 UTC (permalink / raw)
  To: Lawrence Crowl
  Cc: Diego Novillo, Richard Guenther, Nathan Froyd, gcc-patches List

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

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

* Re: Use conditional casting with symtab_node
  2012-10-05  9:52                 ` Jan Hubicka
@ 2012-10-10  0:58                   ` Lawrence Crowl
  2012-10-10 23:46                     ` Diego Novillo
  0 siblings, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-10-10  0:58 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: Richard Guenther, Diego Novillo, gcc-patches List

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?

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-10  0:58                   ` Lawrence Crowl
@ 2012-10-10 23:46                     ` Diego Novillo
  0 siblings, 0 replies; 47+ messages in thread
From: Diego Novillo @ 2012-10-10 23:46 UTC (permalink / raw)
  To: Lawrence Crowl; +Cc: Jan Hubicka, Richard Guenther, gcc-patches List

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.

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

* Re: Use conditional casting with symtab_node
  2012-09-19  9:17       ` Richard Guenther
  2012-09-19 12:19         ` Gabriel Dos Reis
  2012-09-20 13:25         ` Michael Matz
@ 2012-10-11  5:22         ` Xinliang David Li
  2012-10-11 20:26           ` Lawrence Crowl
  2 siblings, 1 reply; 47+ messages in thread
From: Xinliang David Li @ 2012-10-11  5:22 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Eric Botcazou, Lawrence Crowl, gcc-patches, Jan Hubicka, Diego Novillo

In a different thread, I proposed the following alternative to 'try_xxx':

template<typename T> T* symbol::cast_to(symbol* p) {
   if (p->is<T>())
      return static_cast<T*>(p);
   return 0;
 }

cast:

template<typename T> T& symbol:as(symbol* p) {
   assert(p->is<T>())
   return static_cast<T&>(*p);

 }

David

On Wed, Sep 19, 2012 at 2:17 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Sep 19, 2012 at 9:29 AM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>>>
>>> The language syntax would bind the conditional into the intializer, as in
>>>
>>>   if (varpool_node *vnode = (node->try_variable ()
>>>                              && vnode->finalized))
>>>     varpool_analyze_node (vnode);
>>>
>>> which does not type-match.
>>>
>>> So, if you want the type saftey and performance, the cascade is really
>>> unavoidable.
>>
>> Just write:
>>
>>   varpool_node *vnode;
>>
>>   if ((vnode = node->try_variable ()) && vnode->finalized)
>>     varpool_analyze_node (vnode);
>>
>> This has been the standard style for the past 2 decades and trading it for
>> cascading if's is really a bad idea.
>
> Indeed.  Btw, can we not provide a specialization for dynamic_cast <>?
> This ->try_... looks awkward to me compared to the more familiar
>
>   vnode = dynamic_cast <varpool_node> (node)
>
> but yeah - dynamic_cast is not a template ... (but maybe there is some
> standard library piece that mimics it?).
>
> Richard.
>
>> --
>> Eric Botcazou

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

* Re: Use conditional casting with symtab_node
  2012-09-19 19:04           ` Lawrence Crowl
  2012-09-19 21:28             ` Gabriel Dos Reis
@ 2012-10-11  5:31             ` Xinliang David Li
  1 sibling, 0 replies; 47+ messages in thread
From: Xinliang David Li @ 2012-10-11  5:31 UTC (permalink / raw)
  To: Lawrence Crowl
  Cc: Gabriel Dos Reis, Richard Guenther, Eric Botcazou, gcc-patches,
	Jan Hubicka, Diego Novillo

On Wed, Sep 19, 2012 at 11:39 AM, Lawrence Crowl <crowl@googlers.com> wrote:
> On 9/19/12, Gabriel Dos Reis <gdr@integrable-solutions.net> wrote:
>> On Sep 19, 2012 Richard Guenther <richard.guenther@gmail.com> wrote:
>> > Indeed.  Btw, can we not provide a specialization for
>> > dynamic_cast <>?  This ->try_... looks awkward to me compared
>> > to the more familiar
>> >
>> > vnode = dynamic_cast <varpool_node> (node)
>> >
>> > but yeah - dynamic_cast is not a template ... (but maybe there
>> > is some standard library piece that mimics it?).
>>
>> No, it is a language primitive.
>>
>> but we can define out own operation with similar syntax that allows
>> for specialization, whose generic implementation uses dynamic_cast.
>>
>>   template<typename T, typename U>
>>   T* is(U* u) {
>>       return dynamic_cast<T*>(u);
>>   }
>
> At this point, dynamic_cast is not available because we do not
> yet have polymorphic types.  There has been some resistance to
> that notion.
>
> Absent dynamic cast, we need to specialize for various type
> combinations.

The generic implementation can simply assert.

template<typename T> bool symbol::is()
{
  assert (0);
  return true;
}

template <> bool symbol::is<function>()
{
   if (type_ == FUNCTION)
     return true;
  return false;
}

template <> bool symbol::is<variable>()
{
   if (type_ == FUNCTION)
     return false;
  return true;
}

David

>  Function template specialization would be handy,
> but C++ does not directly support that.  We could work around
> that.  However, in the end, the fact that try_whatever is a member
> function means that we can use a notation that depends on context
> and so can be shorter.  That is, we can write 'function' instead of
> 'cgraph_node *'.
>
> --
> Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-05  8:50               ` Richard Guenther
  2012-10-05  9:52                 ` Jan Hubicka
  2012-10-05 10:50                 ` Nathan Froyd
@ 2012-10-11  6:49                 ` Xinliang David Li
  2012-10-11 13:11                   ` Richard Biener
  2 siblings, 1 reply; 47+ messages in thread
From: Xinliang David Li @ 2012-10-11  6:49 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Diego Novillo, Lawrence Crowl, gcc-patches List, Jan Hubicka

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.

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

* Re: Use conditional casting with symtab_node
  2012-10-11  6:49                 ` Xinliang David Li
@ 2012-10-11 13:11                   ` Richard Biener
  0 siblings, 0 replies; 47+ messages in thread
From: Richard Biener @ 2012-10-11 13:11 UTC (permalink / raw)
  To: Xinliang David Li
  Cc: Diego Novillo, Lawrence Crowl, gcc-patches List, Jan Hubicka

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.

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

* Re: Use conditional casting with symtab_node
  2012-10-11  5:22         ` Xinliang David Li
@ 2012-10-11 20:26           ` Lawrence Crowl
  2012-10-11 20:41             ` Xinliang David Li
  0 siblings, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-10-11 20:26 UTC (permalink / raw)
  To: Xinliang David Li
  Cc: Richard Guenther, Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On 10/10/12, Xinliang David Li <davidxl@google.com> wrote:
> In a different thread, I proposed the following alternative to 'try_xxx':
>
> template<typename T> T* symbol::cast_to(symbol* p) {
>    if (p->is<T>())
>       return static_cast<T*>(p);
>    return 0;
>  }
>
> cast:
>
> template<typename T> T& symbol:as(symbol* p) {
>    assert(p->is<T>())
>    return static_cast<T&>(*p);
>
>  }

My concern here was never the technical feasibility, nor the
desirability of having the facility for generic code, but the amount
of the amount of typing in non-generic contexts.  That is

  if (cgraph_node *q = p->try_function ())

versus

  if (cgraph_node *q = p->cast_to <cgraph_node *> ())

I thought the latter would generate objections.  Does anyone object
to the extra typing?

If not, I can make that change.

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-11 20:26           ` Lawrence Crowl
@ 2012-10-11 20:41             ` Xinliang David Li
  2012-10-12  8:24               ` Richard Biener
  0 siblings, 1 reply; 47+ messages in thread
From: Xinliang David Li @ 2012-10-11 20:41 UTC (permalink / raw)
  To: Lawrence Crowl
  Cc: Richard Guenther, Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On Thu, Oct 11, 2012 at 1:23 PM, Lawrence Crowl <crowl@googlers.com> wrote:
> On 10/10/12, Xinliang David Li <davidxl@google.com> wrote:
>> In a different thread, I proposed the following alternative to 'try_xxx':
>>
>> template<typename T> T* symbol::cast_to(symbol* p) {
>>    if (p->is<T>())
>>       return static_cast<T*>(p);
>>    return 0;
>>  }
>>
>> cast:
>>
>> template<typename T> T& symbol:as(symbol* p) {
>>    assert(p->is<T>())
>>    return static_cast<T&>(*p);
>>
>>  }
>
> My concern here was never the technical feasibility, nor the
> desirability of having the facility for generic code, but the amount
> of the amount of typing in non-generic contexts.  That is
>
>   if (cgraph_node *q = p->try_function ())
>
> versus
>
>   if (cgraph_node *q = p->cast_to <cgraph_node *> ())
>
> I thought the latter would generate objections.  Does anyone object
> to the extra typing?
>
> If not, I can make that change.

Think about a more complex class hierarchy and interface consistency.
I believe you don't want this:

tree::try_decl () { .. }
tree::try_ssa_name () { ..}
tree::try_type() {...}
tree::try_int_const () {..}
tree::try_exp () { ...}
 ..

Rather one (or two with the const_cast version).

template <T> T *tree::cast_to ()
{
   if (kind_ == kind_traits<T>::value)
    return static_cast<T*> (this);

 return 0;
}


thanks,

David


>
> --
> Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-11 20:41             ` Xinliang David Li
@ 2012-10-12  8:24               ` Richard Biener
  2012-10-12 19:43                 ` Xinliang David Li
                                   ` (2 more replies)
  0 siblings, 3 replies; 47+ messages in thread
From: Richard Biener @ 2012-10-12  8:24 UTC (permalink / raw)
  To: Xinliang David Li
  Cc: Lawrence Crowl, Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On Thu, Oct 11, 2012 at 10:39 PM, Xinliang David Li <davidxl@google.com> wrote:
> On Thu, Oct 11, 2012 at 1:23 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>> On 10/10/12, Xinliang David Li <davidxl@google.com> wrote:
>>> In a different thread, I proposed the following alternative to 'try_xxx':
>>>
>>> template<typename T> T* symbol::cast_to(symbol* p) {
>>>    if (p->is<T>())
>>>       return static_cast<T*>(p);
>>>    return 0;
>>>  }
>>>
>>> cast:
>>>
>>> template<typename T> T& symbol:as(symbol* p) {
>>>    assert(p->is<T>())
>>>    return static_cast<T&>(*p);
>>>
>>>  }
>>
>> My concern here was never the technical feasibility, nor the
>> desirability of having the facility for generic code, but the amount
>> of the amount of typing in non-generic contexts.  That is
>>
>>   if (cgraph_node *q = p->try_function ())
>>
>> versus
>>
>>   if (cgraph_node *q = p->cast_to <cgraph_node *> ())
>>
>> I thought the latter would generate objections.  Does anyone object
>> to the extra typing?
>>
>> If not, I can make that change.
>
> Think about a more complex class hierarchy and interface consistency.
> I believe you don't want this:
>
> tree::try_decl () { .. }
> tree::try_ssa_name () { ..}
> tree::try_type() {...}
> tree::try_int_const () {..}
> tree::try_exp () { ...}
>  ..
>
> Rather one (or two with the const_cast version).
>
> template <T> T *tree::cast_to ()
> {
>    if (kind_ == kind_traits<T>::value)
>     return static_cast<T*> (this);
>
>  return 0;
> }

I also think that instead of

>>   if (cgraph_node *q = p->cast_to <cgraph_node *> ())

we want

  if ((q = cast_to <cgraph_node *> (p))

I see absolutely no good reason to make cast_to a member, given
that the language has static_cast, const_cast and stuff.  cast_to
would simply be our equivalent to dynamic_cast within our OO model.

Then I'd call it *_cast instead of cast_*, so, why not gcc_cast < >?
Or dyn_cast <> ().  That way

  if ((q = dyn_cast <function *> (p))

would be how to use it.  Small enough, compared to

  if ((q = p->try_function ()))

and a lot more familiar to folks knowing C++ (and probably doesn't make
a difference to others).

Thus, please re-use or follow existing concepts.

As for the example with tree we'd then have

  if ((q = dyn_cast <INTEGER_CST> (p)))

if we can overload on the template parameter kind (can we? typename vs. enum?)
or use tree_cast <> (no I don't want dyn_cast <tree_common> all around the
code).

Thanks,
Richard.

>
> thanks,
>
> David
>
>
>>
>> --
>> Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-12  8:24               ` Richard Biener
@ 2012-10-12 19:43                 ` Xinliang David Li
  2012-10-13 17:56                 ` Lawrence Crowl
  2012-10-14 17:08                 ` Diego Novillo
  2 siblings, 0 replies; 47+ messages in thread
From: Xinliang David Li @ 2012-10-12 19:43 UTC (permalink / raw)
  To: Richard Biener
  Cc: Lawrence Crowl, Eric Botcazou, gcc-patches, Jan Hubicka, Diego Novillo

On Fri, Oct 12, 2012 at 1:22 AM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Thu, Oct 11, 2012 at 10:39 PM, Xinliang David Li <davidxl@google.com> wrote:
>> On Thu, Oct 11, 2012 at 1:23 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>>> On 10/10/12, Xinliang David Li <davidxl@google.com> wrote:
>>>> In a different thread, I proposed the following alternative to 'try_xxx':
>>>>
>>>> template<typename T> T* symbol::cast_to(symbol* p) {
>>>>    if (p->is<T>())
>>>>       return static_cast<T*>(p);
>>>>    return 0;
>>>>  }
>>>>
>>>> cast:
>>>>
>>>> template<typename T> T& symbol:as(symbol* p) {
>>>>    assert(p->is<T>())
>>>>    return static_cast<T&>(*p);
>>>>
>>>>  }
>>>
>>> My concern here was never the technical feasibility, nor the
>>> desirability of having the facility for generic code, but the amount
>>> of the amount of typing in non-generic contexts.  That is
>>>
>>>   if (cgraph_node *q = p->try_function ())
>>>
>>> versus
>>>
>>>   if (cgraph_node *q = p->cast_to <cgraph_node *> ())
>>>
>>> I thought the latter would generate objections.  Does anyone object
>>> to the extra typing?
>>>
>>> If not, I can make that change.
>>
>> Think about a more complex class hierarchy and interface consistency.
>> I believe you don't want this:
>>
>> tree::try_decl () { .. }
>> tree::try_ssa_name () { ..}
>> tree::try_type() {...}
>> tree::try_int_const () {..}
>> tree::try_exp () { ...}
>>  ..
>>
>> Rather one (or two with the const_cast version).
>>
>> template <T> T *tree::cast_to ()
>> {
>>    if (kind_ == kind_traits<T>::value)
>>     return static_cast<T*> (this);
>>
>>  return 0;
>> }
>
> I also think that instead of
>
>>>   if (cgraph_node *q = p->cast_to <cgraph_node *> ())
>
> we want
>
>   if ((q = cast_to <cgraph_node *> (p))
>
> I see absolutely no good reason to make cast_to a member, given
> that the language has static_cast, const_cast and stuff.  cast_to
> would simply be our equivalent to dynamic_cast within our OO model.
>
> Then I'd call it *_cast instead of cast_*, so, why not gcc_cast < >?
> Or dyn_cast <> ().  That way
>
>   if ((q = dyn_cast <function *> (p))
>
> would be how to use it.  Small enough, compared to
>
>   if ((q = p->try_function ()))
>
> and a lot more familiar to folks knowing C++ (and probably doesn't make
> a difference to others).
>
> Thus, please re-use or follow existing concepts.

Agree. dyn_cast<..> for try casting, and cast<..> or gcc_cast<..>
casting with assertion sounds good.


>
> As for the example with tree we'd then have
>
>   if ((q = dyn_cast <INTEGER_CST> (p)))
>
> if we can overload on the template parameter kind (can we? typename vs. enum?)
> or use tree_cast <> (no I don't want dyn_cast <tree_common> all around the
> code).

yes, that also sounds good to me.

thanks,

David

>
> Thanks,
> Richard.
>
>>
>> thanks,
>>
>> David
>>
>>
>>>
>>> --
>>> Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-12  8:24               ` Richard Biener
  2012-10-12 19:43                 ` Xinliang David Li
@ 2012-10-13 17:56                 ` Lawrence Crowl
  2012-10-13 18:04                   ` Gabriel Dos Reis
  2012-10-14 17:08                 ` Diego Novillo
  2 siblings, 1 reply; 47+ messages in thread
From: Lawrence Crowl @ 2012-10-13 17:56 UTC (permalink / raw)
  To: Richard Biener
  Cc: Xinliang David Li, Eric Botcazou, gcc-patches, Jan Hubicka,
	Diego Novillo

On 10/12/12, Richard Biener <richard.guenther@gmail.com> wrote:
> On Oct 11, 2012 Xinliang David Li <davidxl@google.com> wrote:
>> On Oct 11, 2012 Lawrence Crowl <crowl@googlers.com> wrote:
>>> On 10/10/12, Xinliang David Li <davidxl@google.com> wrote:
>>>> In a different thread, I proposed the following alternative to
>>>> 'try_xxx':
>>>>
>>>> template<typename T> T* symbol::cast_to(symbol* p) {
>>>>    if (p->is<T>())
>>>>       return static_cast<T*>(p);
>>>>    return 0;
>>>>  }
>>>>
>>>> cast:
>>>>
>>>> template<typename T> T& symbol:as(symbol* p) {
>>>>    assert(p->is<T>())
>>>>    return static_cast<T&>(*p);
>>>>
>>>>  }
>>>
>>> My concern here was never the technical feasibility, nor the
>>> desirability of having the facility for generic code, but the amount
>>> of the amount of typing in non-generic contexts.  That is
>>>
>>>   if (cgraph_node *q = p->try_function ())
>>>
>>> versus
>>>
>>>   if (cgraph_node *q = p->cast_to <cgraph_node *> ())
>>>
>>> I thought the latter would generate objections.  Does anyone object
>>> to the extra typing?
>>>
>>> If not, I can make that change.
>>
>> Think about a more complex class hierarchy and interface consistency.
>> I believe you don't want this:
>>
>> tree::try_decl () { .. }
>> tree::try_ssa_name () { ..}
>> tree::try_type() {...}
>> tree::try_int_const () {..}
>> tree::try_exp () { ...}
>>  ..
>>
>> Rather one (or two with the const_cast version).
>>
>> template <T> T *tree::cast_to ()
>> {
>>    if (kind_ == kind_traits<T>::value)
>>     return static_cast<T*> (this);
>>
>>  return 0;
>> }
>
> I also think that instead of
>
>>>   if (cgraph_node *q = p->cast_to <cgraph_node *> ())
>
> we want
>
>   if ((q = cast_to <cgraph_node *> (p))
>
> I see absolutely no good reason to make cast_to a member, given
> that the language has static_cast, const_cast and stuff.  cast_to
> would simply be our equivalent to dynamic_cast within our OO model.

Sorry, that was a think-o.  Agreed there is no point in it being a
member.

> Then I'd call it *_cast instead of cast_*, so, why not gcc_cast < >?
> Or dyn_cast <> ().  That way
>
>   if ((q = dyn_cast <function *> (p))
>
> would be how to use it.

Which function?  The point with my original proposal is that the
kind of function was derivable from context, and thus can be shorter.

> Small enough, compared to
>
>   if ((q = p->try_function ()))
>
> and a lot more familiar to folks knowing C++ (and probably doesn't
> make a difference to others).
>
> Thus, please re-use or follow existing concepts.

Both are existing concepts.  What I proposed is a common technique
for avoiding the cost of dynamic_cast when down casting in a class
hierarchy.  Both concepts will work.  I proposed what I thought
would be most convenient to programmers.  However, I will change
to the other form unless someone objects.

> As for the example with tree we'd then have
>
>   if ((q = dyn_cast <INTEGER_CST> (p)))
>
> if we can overload on the template parameter kind (can we?
> typename vs.  enum?)

There are two template parameters, one for the argument type and
one for the return type.  We can overload on the argument type but
not on the return type.  We can, however, (indirectly) partially
specialize on the return type.  We need to do that anyway to
represent the fact that not all type conversions are legal.

However, I recommend against specializing on the enum, as it would
become somewhat obscure when the hierarchy is discriminated on more
than one enum.

> or use tree_cast <> (no I don't want dyn_cast <tree_common>
> all around the code).

Once we have proper class hierarchies, derived to base conversions
are implicit.  In the meantime, we need something else.

-- 
Lawrence Crowl

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

* Re: Use conditional casting with symtab_node
  2012-10-13 17:56                 ` Lawrence Crowl
@ 2012-10-13 18:04                   ` Gabriel Dos Reis
  0 siblings, 0 replies; 47+ messages in thread
From: Gabriel Dos Reis @ 2012-10-13 18:04 UTC (permalink / raw)
  To: Lawrence Crowl
  Cc: Richard Biener, Xinliang David Li, Eric Botcazou, gcc-patches,
	Jan Hubicka, Diego Novillo

On Sat, Oct 13, 2012 at 12:44 PM, Lawrence Crowl <crowl@googlers.com> wrote:

>> Thus, please re-use or follow existing concepts.
>
> Both are existing concepts.  What I proposed is a common technique
> for avoiding the cost of dynamic_cast when down casting in a class
> hierarchy.  Both concepts will work.  I proposed what I thought
> would be most convenient to programmers.  However, I will change
> to the other form unless someone objects.

Let me elaborate on your point.

The concept you are trying to implement is that of:
   (a) check whether a tree is of a certain kind;
   (b) if so return a pointer to the (sub-)object of that kind;
         otherwise a null pointer.

This is a standard idiom -- at least when using C++.

It can be implemented in various ways.  Your earlier attempt
try_xxx is one example.  Another common example, built into
the language is dynamic_cast.  The latter requires that classes
involved in this test be polymorphic (because the builtin implementation
needs to consult metadata that are already present with virtual
functions.)  Yet, another implementation is what is currently in GCC
more-or-less.

I think we should name the operation based on the abstract concept
we are implementing as opposed the builtin language implementation.
That is why I recommend is<> over dyn_cast<> or variations of it.

We should be able to understand its uses without having to know
the implementation details.


> However, I recommend against specializing on the enum, as it would
> become somewhat obscure when the hierarchy is discriminated on more
> than one enum.

100% agreed.

-- Gaby

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

* Re: Use conditional casting with symtab_node
  2012-10-12  8:24               ` Richard Biener
  2012-10-12 19:43                 ` Xinliang David Li
  2012-10-13 17:56                 ` Lawrence Crowl
@ 2012-10-14 17:08                 ` Diego Novillo
  2 siblings, 0 replies; 47+ messages in thread
From: Diego Novillo @ 2012-10-14 17:08 UTC (permalink / raw)
  To: Richard Biener
  Cc: Xinliang David Li, Lawrence Crowl, Eric Botcazou, gcc-patches,
	Jan Hubicka

On Fri, Oct 12, 2012 at 4:22 AM, Richard Biener
<richard.guenther@gmail.com> wrote:

> I also think that instead of
>
>>>   if (cgraph_node *q = p->cast_to <cgraph_node *> ())
>
> we want
>
>   if ((q = cast_to <cgraph_node *> (p))
>
> I see absolutely no good reason to make cast_to a member, given
> that the language has static_cast, const_cast and stuff.  cast_to
> would simply be our equivalent to dynamic_cast within our OO model.
>
> Then I'd call it *_cast instead of cast_*, so, why not gcc_cast < >?
> Or dyn_cast <> ().  That way
>
>   if ((q = dyn_cast <function *> (p))

This looks fine to me.


Diego.

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

end of thread, other threads:[~2012-10-14 15:16 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-18 18:02 Use conditional casting with symtab_node Lawrence Crowl
2012-09-18 18:09 ` Eric Botcazou
2012-09-18 18:37   ` Lawrence Crowl
2012-09-19  7:31     ` Eric Botcazou
2012-09-19  9:17       ` Richard Guenther
2012-09-19 12:19         ` Gabriel Dos Reis
2012-09-19 19:04           ` Lawrence Crowl
2012-09-19 21:28             ` Gabriel Dos Reis
2012-09-19 22:03               ` Lawrence Crowl
2012-10-11  5:31             ` Xinliang David Li
2012-09-20 13:25         ` Michael Matz
2012-10-11  5:22         ` Xinliang David Li
2012-10-11 20:26           ` Lawrence Crowl
2012-10-11 20:41             ` Xinliang David Li
2012-10-12  8:24               ` Richard Biener
2012-10-12 19:43                 ` Xinliang David Li
2012-10-13 17:56                 ` Lawrence Crowl
2012-10-13 18:04                   ` Gabriel Dos Reis
2012-10-14 17:08                 ` Diego Novillo
2012-09-19 18:39       ` Lawrence Crowl
2012-09-20 13:26         ` Michael Matz
2012-09-20 20:01           ` Lawrence Crowl
2012-09-20 22:02             ` Gabriel Dos Reis
2012-09-20 22:06               ` Lawrence Crowl
2012-09-18 19:57 ` Richard Guenther
2012-09-18 20:32   ` Lawrence Crowl
2012-09-22  6:07 ` Lawrence Crowl
2012-09-25 21:25   ` Lawrence Crowl
2012-10-03  0:32   ` Lawrence Crowl
2012-10-03 12:07     ` Martin Jambor
2012-10-03 16:53       ` Lawrence Crowl
2012-10-04  8:00         ` Richard Guenther
2012-10-04 18:14           ` Lawrence Crowl
2012-10-04 18:17             ` Diego Novillo
2012-10-05  8:50               ` Richard Guenther
2012-10-05  9:52                 ` Jan Hubicka
2012-10-10  0:58                   ` Lawrence Crowl
2012-10-10 23:46                     ` Diego Novillo
2012-10-05 10:50                 ` Nathan Froyd
2012-10-05 11:05                   ` Richard Guenther
2012-10-05 12:44                     ` Diego Novillo
2012-10-05 13:58                       ` Steven Bosscher
2012-10-05 14:07                       ` Steven Bosscher
2012-10-05 21:50                       ` Lawrence Crowl
2012-10-05 22:04                         ` Steven Bosscher
2012-10-11  6:49                 ` Xinliang David Li
2012-10-11 13:11                   ` Richard Biener

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