Patchwork Apply conditional down cast to cgraph.h et.al.

login
register
mail settings
Submitter Lawrence Crowl
Date Oct. 31, 2012, 11:17 p.m.
Message ID <CAGqM8fZS2EfmNs15hkwuyFRaZXFhguoz4b6ww=ZEcd+D=9Bm3g@mail.gmail.com>
Download mbox | patch
Permalink /patch/196047/
State New
Headers show

Comments

Lawrence Crowl - Oct. 31, 2012, 11:17 p.m.
On 10/30/12, Lawrence Crowl <crowl@googlers.com> wrote:
> On 10/30/12, Diego Novillo <dnovillo@google.com> wrote:
>> On Tue, Oct 30, 2012 at 4:53 PM, Lawrence Crowl <crowl@googlers.com> wrote:
>>> On 10/30/12, Diego Novillo <dnovillo@google.com> wrote:
>>>>
>>>> So, to use these three functions, the user must define this single
>>>> 'is_a_helper' routine?  Nothing else?
>>>
>>> You need to distinguish which kind user.  Someone just wanting
>>> to convert does not need to know about the is_a_helper stuff.
>>> Someone wanting to extend the set of type relationships needs to
>>> provide one or two template specializations.  I've modified the
>>> in-header documentation to better reflect the distinction.
>>
>> Great.
>>
>>> I originally had
>>>
>>>   if (cgraph_node *ce = dyn_cast <cgraph_node> (e))
>>>     if (!DECL_BUILT_IN (e->symbol.decl))
>>>       lto_cgraph_replace_node (ce, cgraph (prevailing));
>>>
>>> but folks objected to increasing the nesting, and asked that I
>>> change to the pre-declare form.
>>
>> Ah, yeah.  I remember that.  OK, so we can now use both forms, right?
>
> Yes.
>
> I will commit the patch as soon as the merge and test is complete.

Committed as follows.

This patch implements generic type query and conversion functions,
and applies them to the use of cgraph_node, varpool_node, and symtab_node.

The functions are:

bool is_a <TYPE> (pointer)
  Tests whether the pointer actually points to a more derived TYPE.

TYPE *as_a <TYPE> (pointer)
  Converts pointer to a TYPE*.

TYPE *dyn_cast <TYPE> (pointer)
  Converts pointer to TYPE* if and only if "is_a <TYPE> pointer".
  Otherwise, returns NULL.
  This function is essentially a checked down cast.

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 = dyn_cast <cgraph_node> (node))
    {
      ....
    }

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 = dyn_cast <varpool_node> (node);
  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 functions is_a <cgraph_node> and is_a <varpool_node>.  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.

Tested on x86_64.


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

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

@@ -1141,7 +1141,7 @@ lsei_next_variable_in_partition (lto_sym
 {
   lsei_next (lsei);
   while (!lsei_end_p (*lsei)
-	 && (!symtab_variable_p (lsei_node (*lsei))
+	 && (!is_a <varpool_node> (lsei_node (*lsei))
 	     || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
(*lsei))))
     lsei_next (lsei);
 }
@@ -1154,7 +1154,7 @@ lsei_start_variable_in_partition (lto_sy

   if (lsei_end_p (lsei))
     return lsei;
-  if (!symtab_variable_p (lsei_node (lsei))
+  if (!is_a <varpool_node> (lsei_node (lsei))
       || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
     lsei_next_variable_in_partition (&lsei);
Eric Botcazou - Nov. 2, 2012, 8:27 a.m.
> Index: gcc/ChangeLog
> 
> 2012-10-31  Lawrence Crowl  <crowl@google.com>
> 
> 	* is-a.h: New.
> 	(is_a <T> (U*)): New.  Test for is-a relationship.
> 	(as_a <T> (U*)): New.  Treat as a derived type.
> 	(dyn_cast <T> (U*)): New.  Conditionally cast based on is_a.
> 	* cgraph.h (varpool_node): Rename to varpool_node_for_decl.
> 	Adjust callers to match.
> 	(is_a_helper <cgraph_node>::test (symtab_node_def *)): New.
> 	(is_a_helper <varpool_node>::test (symtab_node_def *)): New.
> 	(symtab_node_def::try_function): New.  Change most calls to
> 	symtab_function_p with calls to dyn_cast <cgraph_node> (p).
> 	(symtab_node_def::try_variable): New.  Change most calls to
> 	symtab_variable_p with calls to dyn_cast <varpool_node> (p).
> 	(symtab_function_p): Remove.  Change callers to use
>         is_a <cgraph_node> (p) instead.
> 	(symtab_variable_p): Remove.  Change callers to use
>         is_a <varpool_node> (p) instead.
> 	* 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.
> 	* Makefile.in (CGRAPH_H): Add is-a.h as used by cgraph.h.

The installed patch touches the ada/, cp/ and lto/ subdirectories without 
modifying their ChangeLog files.  Please add the missing entries.

[Some people, like me, do use these ChangeLogs to synchronize trees]
Lawrence Crowl - Nov. 2, 2012, 8:02 p.m.
On 11/2/12, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> Index: gcc/ChangeLog
>>
>> 2012-10-31  Lawrence Crowl  <crowl@google.com>
>>
>> 	* is-a.h: New.
>> 	(is_a <T> (U*)): New.  Test for is-a relationship.
>> 	(as_a <T> (U*)): New.  Treat as a derived type.
>> 	(dyn_cast <T> (U*)): New.  Conditionally cast based on is_a.
>> 	* cgraph.h (varpool_node): Rename to varpool_node_for_decl.
>> 	Adjust callers to match.
>> 	(is_a_helper <cgraph_node>::test (symtab_node_def *)): New.
>> 	(is_a_helper <varpool_node>::test (symtab_node_def *)): New.
>> 	(symtab_node_def::try_function): New.  Change most calls to
>> 	symtab_function_p with calls to dyn_cast <cgraph_node> (p).
>> 	(symtab_node_def::try_variable): New.  Change most calls to
>> 	symtab_variable_p with calls to dyn_cast <varpool_node> (p).
>> 	(symtab_function_p): Remove.  Change callers to use
>>         is_a <cgraph_node> (p) instead.
>> 	(symtab_variable_p): Remove.  Change callers to use
>>         is_a <varpool_node> (p) instead.
>> 	* 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.
>> 	* Makefile.in (CGRAPH_H): Add is-a.h as used by cgraph.h.
>
> The installed patch touches the ada/, cp/ and lto/ subdirectories without
> modifying their ChangeLog files.  Please add the missing entries.
>
> [Some people, like me, do use these ChangeLogs to synchronize trees]

Done and committed.


Update ChangeLog files as requested for cgraph change to checked down cast.


Index: gcc/cp/ChangeLog

2012-10-31  Lawrence Crowl  <crowl@google.com>

	* decl2.c (var_finalized_p): Rename varpool_node to
	varpool_node_for_decl.
	(maybe_emit_vtables): Likewise.

Index: gcc/ada/ChangeLog

2012-10-31  Lawrence Crowl  <crowl@google.com>

	* gcc-interface/utils.c (gnat_write_global_declarations):
	Rename varpool_node to varpool_node_for_decl.

Index: gcc/lto/ChangeLog

2012-10-31  Lawrence Crowl  <crowl@google.com>

	* lto.c (lto_wpa_write_files): Change symtab checking to a checked
	down-cast via dyn_cast.
	* lto-partition.c (add_symbol_to_partition_1): Likewise.
	(undo_partition): Likewise.
	(lto_balanced_map): Likewise.
	(get_symbol_class): Likewise and via is_a.
	(lto_balanced_map): Change symtab checking to is_a.
Eric Botcazou - Nov. 5, 2012, 11:06 a.m.
> Done and committed.

That's great, thanks!

Patch

Index: gcc/ChangeLog

2012-10-31  Lawrence Crowl  <crowl@google.com>

	* is-a.h: New.
	(is_a <T> (U*)): New.  Test for is-a relationship.
	(as_a <T> (U*)): New.  Treat as a derived type.
	(dyn_cast <T> (U*)): New.  Conditionally cast based on is_a.
	* cgraph.h (varpool_node): Rename to varpool_node_for_decl.
	Adjust callers to match.
	(is_a_helper <cgraph_node>::test (symtab_node_def *)): New.
	(is_a_helper <varpool_node>::test (symtab_node_def *)): New.
	(symtab_node_def::try_function): New.  Change most calls to
	symtab_function_p with calls to dyn_cast <cgraph_node> (p).
	(symtab_node_def::try_variable): New.  Change most calls to
	symtab_variable_p with calls to dyn_cast <varpool_node> (p).
	(symtab_function_p): Remove.  Change callers to use
        is_a <cgraph_node> (p) instead.
	(symtab_variable_p): Remove.  Change callers to use
        is_a <varpool_node> (p) instead.
	* 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.
	* Makefile.in (CGRAPH_H): Add is-a.h as used by cgraph.h.

Index: gcc/is-a.h
===================================================================
--- gcc/is-a.h	(revision 0)
+++ gcc/is-a.h	(revision 0)
@@ -0,0 +1,201 @@ 
+/* Dynamic testing for abstract is-a relationships.
+   Copyright (C) 2012 Free Software Foundation, Inc.
+   Contributed by Lawrence Crowl.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* This header generic type query and conversion functions.
+
+
+USING THE GENERIC TYPE FACILITY
+
+
+The user functions are:
+
+bool is_a <TYPE> (pointer)
+
+    Tests whether the pointer actually points to a more derived TYPE.
+
+    Suppose you have a symtab_node_def *ptr, AKA symtab_node ptr.  You can test
+    whether it points to a 'derived' cgraph_node as follows.
+
+      if (is_a <cgraph_node> (ptr))
+        ....
+
+
+TYPE *as_a <TYPE> (pointer)
+
+    Converts pointer to a TYPE*.
+
+    You can just assume that it is such a node.
+
+      do_something_with (as_a <cgraph_node> *ptr);
+
+TYPE *dyn_cast <TYPE> (pointer)
+
+    Converts pointer to TYPE* if and only if "is_a <TYPE> pointer".  Otherwise,
+    returns NULL.  This function is essentially a checked down cast.
+
+    This functions reduce compile time and increase type safety when treating a
+    generic item as a more specific item.
+
+    You can test and obtain a pointer to the 'derived' type in one indivisible
+    operation.
+
+      if (cgraph_node *cptr = dyn_cast <cgraph_node> (ptr))
+        ....
+
+    As an example, the code change is from
+
+      if (symtab_function_p (node))
+        {
+          struct cgraph_node *cnode = cgraph (node);
+          ....
+        }
+
+    to
+
+      if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
+        {
+          ....
+        }
+
+    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 approach
+    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 = dyn_cast <varpool_node> (node);
+      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.
+
+
+If you use these functions and get a 'inline function not defined' or a
+'missing symbol' error message for 'is_a_helper<....>::test', it means that
+the connection between the types has not been made.  See below.
+
+
+EXTENDING THE GENERIC TYPE FACILITY
+
+Each connection between types must be made by defining a specialization of the
+template member function 'test' of the template class 'is_a_helper'.  For
+example,
+
+  template <>
+  template <>
+  inline bool
+  is_a_helper <cgraph_node>::test (symtab_node_def *p)
+  {
+    return p->symbol.type == SYMTAB_FUNCTION;
+  }
+
+If a simple reinterpret_cast between the pointer types is incorrect, then you
+must also specialize the template member function 'cast'.  Failure to do so
+when needed may result in a crash.  For example,
+
+  template <>
+  template <>
+  inline bool
+  is_a_helper <cgraph_node>::cast (symtab_node_def *p)
+  {
+    return &p->x_function;
+  }
+
+*/
+
+#ifndef GCC_IS_A_H
+#define GCC_IS_A_H
+
+/* A generic type conversion internal helper class.  */
+
+template <typename T>
+struct is_a_helper
+{
+  template <typename U>
+  static inline bool test (U *p);
+  template <typename U>
+  static inline T *cast (U *p);
+};
+
+/* Note that we deliberately do not define the 'test' member template.  Not
+   doing so will result in a build-time error for type relationships that have
+   not been defined, rather than a run-time error.  See the discussion above
+   for when to define this member.  */
+
+/* This is the generic implementation for casting from one type to another.
+   Do not use this routine directly; it is an internal function.  See the
+   discussion above for when to define this member.  */
+
+template <typename T>
+template <typename U>
+inline T *
+is_a_helper <T>::cast (U *p)
+{
+  return reinterpret_cast <T *> (p);
+}
+
+
+/* The public interface.  */
+
+/* A generic test for a type relationship.  See the discussion above for when
+   to use this function.  The question answered is "Is type T a derived type of
+   type U?".  */
+
+template <typename T, typename U>
+inline bool
+is_a (U *p)
+{
+  return is_a_helper<T>::test (p);
+}
+
+/* A generic conversion from a base type U to a derived type T.  See the
+   discussion above for when to use this function.  */
+
+template <typename T, typename U>
+inline T *
+as_a (U *p)
+{
+  gcc_assert (is_a <T> (p));
+  return is_a_helper <T>::cast (p);
+}
+
+/* A generic checked conversion from a base type U to a derived type T.  See
+   the discussion above for when to use this function.  */
+
+template <typename T, typename U>
+inline T *
+dyn_cast (U *p)
+{
+  if (is_a <T> (p))
+    return is_a_helper <T>::cast (p);
+  else
+    return static_cast <T *> (0);
+}
+
+#endif  /* GCC_IS_A_H  */
Index: gcc/lto-symtab.c
===================================================================
--- gcc/lto-symtab.c	(revision 193006)
+++ gcc/lto-symtab.c	(working copy)
@@ -532,11 +532,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 = dyn_cast <cgraph_node> (e);
+      if (ce && !DECL_BUILT_IN (e->symbol.decl))
+	lto_cgraph_replace_node (ce, cgraph (prevailing));
+      if (varpool_node *ve = dyn_cast <varpool_node> (e))
+	lto_varpool_replace_node (ve, varpool (prevailing));
     }

   return;
Index: gcc/cgraphbuild.c
===================================================================
--- gcc/cgraphbuild.c	(revision 193006)
+++ 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 193006)
+++ 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 = dyn_cast <cgraph_node> (node);
+      if (cn && !cn->global.inlined_to)
+	return cn;
+    }
   return NULL;
 }

Index: gcc/cgraph.h
===================================================================
--- gcc/cgraph.h	(revision 193006)
+++ gcc/cgraph.h	(working copy)
@@ -22,6 +22,7 @@  along with GCC; see the file COPYING3.
 #ifndef GCC_CGRAPH_H
 #define GCC_CGRAPH_H

+#include "is-a.h"
 #include "plugin-api.h"
 #include "vec.h"
 #include "tree.h"
@@ -457,12 +458,32 @@  struct GTY(()) asm_node {
 union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"),
 	   chain_prev ("%h.symbol.previous"))) symtab_node_def {
   struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol;
-  /* Use cgraph (symbol) accessor to get cgraph_node.  */
+  /* To access the following fields,
+     use the use dyn_cast or as_a to obtain the concrete type.  */
   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.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <cgraph_node>::test (symtab_node_def *p)
+{
+  return p->symbol.type == SYMTAB_FUNCTION;
+}
+
+/* Report whether or not THIS symtab node is a vriable, aka varpool_node.  */
+
+template <>
+template <>
+inline bool
+is_a_helper <varpool_node>::test (symtab_node_def *p)
+{
+  return p->symbol.type == SYMTAB_VARIABLE;
+}
+
 extern GTY(()) symtab_node symtab_nodes;
 extern GTY(()) int cgraph_n_nodes;
 extern GTY(()) int cgraph_max_uid;
@@ -685,7 +706,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 +736,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 +808,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 = dyn_cast <varpool_node> (node))
+      return vnode;
   return NULL;
 }

@@ -813,10 +819,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 = dyn_cast <varpool_node> (node1))
+      return vnode1;
   return NULL;
 }
 /* Walk all variables.  */
@@ -832,9 +836,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 = dyn_cast <varpool_node> (node);
+      if (vnode && DECL_INITIAL (node->symbol.decl))
+	return vnode;
     }
   return NULL;
 }
@@ -846,9 +850,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 = dyn_cast <varpool_node> (node1);
+      if (vnode1 && DECL_INITIAL (node1->symbol.decl))
+	return vnode1;
     }
   return NULL;
 }
@@ -865,8 +869,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 = dyn_cast <varpool_node> (node);
+      if (vnode && vnode->analyzed)
+	return vnode;
     }
   return NULL;
 }
@@ -878,8 +883,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 = dyn_cast <varpool_node> (node1);
+      if (vnode1 && vnode1->analyzed)
+	return vnode1;
     }
   return NULL;
 }
@@ -895,8 +901,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 = dyn_cast <cgraph_node> (node);
+      if (cn && cn->analyzed)
+	return cn;
     }
   return NULL;
 }
@@ -908,8 +915,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 = dyn_cast <cgraph_node> (node1);
+      if (cn1 && cn1->analyzed)
+	return cn1;
     }
   return NULL;
 }
@@ -925,10 +933,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 = dyn_cast <cgraph_node> (node))
+      return cn;
   return NULL;
 }

@@ -938,10 +944,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 = dyn_cast <cgraph_node> (node1))
+      return cn1;
   return NULL;
 }
 /* Walk all functions.  */
@@ -968,9 +972,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 = dyn_cast <cgraph_node> (node);
+      if (cn && cgraph_function_with_gimple_body_p (cn))
+	return cn;
     }
   return NULL;
 }
@@ -982,9 +986,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 = dyn_cast <cgraph_node> (node1);
+      if (cn1 && cgraph_function_with_gimple_body_p (cn1))
+	return cn1;
     }
   return NULL;
 }
@@ -1183,7 +1187,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 (is_a <cgraph_node> (ref->referred))
     return ipa_ref_node (ref);
   return NULL;
 }
@@ -1197,7 +1201,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 (is_a <varpool_node> (ref->referred))
     return ipa_ref_varpool_node (ref);
   return NULL;
 }
@@ -1328,7 +1332,7 @@  symtab_real_symbol_p (symtab_node node)
   struct cgraph_node *cnode;
   struct ipa_ref *ref;

-  if (!symtab_function_p (node))
+  if (!is_a <cgraph_node> (node))
     return true;
   cnode = cgraph (node);
   if (cnode->global.inlined_to)
Index: gcc/tree-emutls.c
===================================================================
--- gcc/tree-emutls.c	(revision 193006)
+++ 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 193006)
+++ 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 (!is_a <varpool_node> (ref->referred))
 	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 = dyn_cast <varpool_node> (snode);
+      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 = dyn_cast <cgraph_node> (snode);
+	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 = dyn_cast <cgraph_node> (snode);
+	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 193006)
+++ 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 = dyn_cast <cgraph_node> (node);
+  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 NODE is finalized and needed.  */
+
+inline static bool
+symbol_finalized_and_needed (symtab_node node)
+{
+  if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
+    return cnode->local.finalized
+	   && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl);
+  if (varpool_node *vnode = dyn_cast <varpool_node> (node))
+    return vnode->finalized
+	   && !DECL_EXTERNAL (vnode->symbol.decl)
+	   && decide_is_variable_needed (vnode, vnode->symbol.decl);
+  return false;
+}
+
+/* Determine if a symbol NODE is finalized.  */
+
+inline static bool
+symbol_finalized (symtab_node node)
+{
+  if (cgraph_node *cnode= dyn_cast <cgraph_node> (node))
+    return cnode->local.finalized;
+  if (varpool_node *vnode = dyn_cast <varpool_node> (node))
+    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 = dyn_cast <cgraph_node> (node);
+	  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 = dyn_cast <varpool_node> (node);
+	      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 = dyn_cast <cgraph_node> (node))
 	{
 	  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 && is_a <cgraph_node> (target_node))
 	{
 	  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 && is_a <varpool_node> (target_node))
 	{
 	  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 193006)
+++ gcc/cp/decl2.c	(working copy)
@@ -1775,7 +1775,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,
@@ -1893,7 +1893,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 193006)
+++ 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 || is_a <cgraph_node> (referring_node));
   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 193006)
+++ gcc/lto-cgraph.c	(working copy)
@@ -679,7 +679,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 (is_a <cgraph_node> (ref->referred))
       add_node_to (encoder, ipa_ref_node (ref), false);
     else
       lto_symtab_encoder_encode (encoder, ref->referred);
@@ -730,9 +730,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 = dyn_cast <varpool_node> (node))
 	{
-	  struct varpool_node *vnode = varpool (node);
 	  if (DECL_INITIAL (vnode->symbol.decl)
 	      && !lto_symtab_encoder_encode_initializer_p (encoder,
 							   vnode)
@@ -796,8 +795,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 = dyn_cast <cgraph_node> (node))
+        lto_output_node (ob, cnode, encoder);
       else
         lto_output_varpool_node (ob, varpool (node), encoder);
 	
@@ -983,7 +982,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;
@@ -1144,14 +1143,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 || !is_a <cgraph_node> (node));
 #endif
   FOR_EACH_VEC_ELT (symtab_node, nodes, i, node)
     {
       int ref;
-      if (symtab_function_p (node))
+      if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
 	{
-	  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)
@@ -1160,9 +1159,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;
@@ -1174,7 +1173,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 = is_a <cgraph_node> (node) ? (void *)1 : NULL;
   return nodes;
 }

@@ -1449,7 +1448,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);
@@ -1459,18 +1457,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 = dyn_cast <cgraph_node> (node);
+      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 = dyn_cast <cgraph_node> (node);
+      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 193006)
+++ gcc/lto-streamer-out.c	(working copy)
@@ -956,7 +956,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 ();
@@ -972,10 +971,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 = dyn_cast <cgraph_node> (snode);
+      if (node
+	  && lto_symtab_encoder_encode_body_p (encoder, node)
 	  && !node->alias
 	  && !node->thunk.thunk_p)
 	{
Index: gcc/ada/gcc-interface/utils.c
===================================================================
--- gcc/ada/gcc-interface/utils.c	(revision 193006)
+++ gcc/ada/gcc-interface/utils.c	(working copy)
@@ -5586,7 +5586,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 193006)
+++ 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 (is_a <cgraph_node> (ref->referred))
 	{
 	  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 = dyn_cast <cgraph_node> (node))
 	{
-	  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 = dyn_cast <varpool_node> (node);
+      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 (is_a <cgraph_node> (ref->referring))
 	  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 193006)
+++ gcc/ipa-inline-analysis.c	(working copy)
@@ -3855,22 +3855,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 = dyn_cast <cgraph_node> (snode);
+      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 = dyn_cast <cgraph_node> (snode);
+      if (cnode && (node = cnode)->analyzed)
 	{
 	  struct inline_summary *info = inline_summary (node);
 	  struct bitpack_d bp;
@@ -3878,7 +3881,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);
@@ -3897,7 +3900,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 193006)
+++ gcc/lto/lto.c	(working copy)
@@ -2671,12 +2671,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 = dyn_cast <cgraph_node> (node);
+		  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 = dyn_cast <varpool_node> (node);
+		      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 193006)
+++ 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 = dyn_cast <cgraph_node> (node);
+  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 = dyn_cast <varpool_node> (node))
     {
       /* 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 (is_a <varpool_node> (ref->referred)
 	     && 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 = dyn_cast <cgraph_node> (node))
     {
-      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 = dyn_cast <cgraph_node> (node))
     {
-      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 = dyn_cast <varpool_node> (node))
+    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 = dyn_cast <cgraph_node> (node))
+        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 = dyn_cast <cgraph_node> (snode))
 	    {
 	      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 (is_a <varpool_node> (ref->referred))
 	      {
 		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 (is_a <varpool_node> (ref->referring))
 	      {
 		int index;

Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(revision 193006)
+++ 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 193006)
+++ 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 (is_a <varpool_node> (node) && 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 = dyn_cast <cgraph_node> (node))
+	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 = dyn_cast <cgraph_node> (node))
+    cgraph_remove_node (cnode);
+  else if (varpool_node *vnode = dyn_cast <varpool_node> (node))
+    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 = dyn_cast <cgraph_node> (node))
+    dump_cgraph_node (f, cnode);
+  else if (varpool_node *vnode = dyn_cast <varpool_node> (node))
+    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 (is_a <cgraph_node> (node))
     {
       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 (is_a <varpool_node> (node))
     {
       if (TREE_CODE (node->symbol.decl) != VAR_DECL)
 	{
@@ -622,7 +622,8 @@  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)))
+          && !(is_a <varpool_node> (node)
+	       || DECL_HARD_REGISTER (node->symbol.decl)))
 	{
           error ("node not found in symtab assembler name hash");
           error_found = true;
@@ -676,8 +677,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 = dyn_cast <cgraph_node> (node))
+    verify_cgraph_node (cnode);
   else
     if (verify_symtab_base (node))
       {
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 193006)
+++ gcc/Makefile.in	(working copy)
@@ -886,7 +886,7 @@  CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) v
 IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
 IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H)
 CGRAPH_H = cgraph.h $(VEC_H) $(TREE_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \
-	cif-code.def ipa-ref.h ipa-ref-inline.h $(LINKER_PLUGIN_API_H)
+	cif-code.def ipa-ref.h ipa-ref-inline.h $(LINKER_PLUGIN_API_H) is-a.h
 DF_H = df.h $(BITMAP_H) $(REGSET_H) sbitmap.h $(BASIC_BLOCK_H) \
 	alloc-pool.h $(TIMEVAR_H)
 VALTRACK_H = valtrack.h $(BITMAP_H) $(DF_H) $(RTL_H) $(BASIC_BLOCK_H) \
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 193006)
+++ 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 193006)
+++ 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 = dyn_cast <varpool_node> (node))
+      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 = dyn_cast <varpool_node> (next);
+	      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 = dyn_cast <varpool_node> (ref->referred);
+	  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 193006)
+++ gcc/lto-streamer.h	(working copy)
@@ -1115,7 +1115,7 @@  lsei_next_function_in_partition (lto_sym
 {
   lsei_next (lsei);
   while (!lsei_end_p (*lsei)
-	 && (!symtab_function_p (lsei_node (*lsei))
+	 && (!is_a <cgraph_node> (lsei_node (*lsei))
 	     || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node
(*lsei))))
     lsei_next (lsei);