pr60092.c: Remove default dg-skip-if arguments.
[gcc.git] / gcc / cgraph.h
index 7b9098bad04cf2f8e48fad929e5dc3ed10b8fe30..59d9ce66845f1dec91d29aa3b19effbc596133e2 100644 (file)
@@ -1,6 +1,5 @@
 /* Callgraph handling code.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-   2012 Free Software Foundation, Inc.
+   Copyright (C) 2003-2014 Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
 This file is part of GCC.
@@ -22,15 +21,15 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_CGRAPH_H
 #define GCC_CGRAPH_H
 
+#include "is-a.h"
 #include "plugin-api.h"
 #include "vec.h"
-#include "tree.h"
 #include "basic-block.h"
 #include "function.h"
 #include "ipa-ref.h"
 
 /* Symbol table consists of functions and variables.
-   TODO: add labels, constant pool and aliases.  */
+   TODO: add labels and CONST_DECLs.  */
 enum symtab_type
 {
   SYMTAB_SYMBOL,
@@ -40,46 +39,118 @@ enum symtab_type
 
 /* Base of all entries in the symbol table.
    The symtab_node is inherited by cgraph and varpol nodes.  */
-struct GTY(()) symtab_node_base
+class GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"),
+          chain_next ("%h.next"), chain_prev ("%h.previous")))
+  symtab_node
 {
+public:
+  /* Return name.  */
+  const char *name () const;
+
+  /* Return asm name.  */
+  const char * asm_name () const;
+
   /* Type of the symbol.  */
-  enum symtab_type type;
-  tree decl;
-  struct ipa_ref_list ref_list;
-  /* Circular list of nodes in the same comdat group if non-NULL.  */
-  symtab_node same_comdat_group;
-  /* Ordering of all symtab entries.  */
-  int order;
-  enum ld_plugin_symbol_resolution resolution;
-  /* File stream where this node is being written to.  */
-  struct lto_file_decl_data * lto_file_data;
+  ENUM_BITFIELD (symtab_type) type : 8;
 
-  /* Linked list of symbol table entries starting with symtab_nodes.  */
-  symtab_node next;
-  symtab_node previous;
-  /* Linked list of symbols with the same asm name.  There may be multiple
-     entries for single symbol name in the case of LTO resolutions,
-     existence of inline clones, or duplicated declaration. The last case
-     is a long standing bug frontends and builtin handling. */
-  symtab_node next_sharing_asm_name;
-  symtab_node previous_sharing_asm_name;
+  /* The symbols resolution.  */
+  ENUM_BITFIELD (ld_plugin_symbol_resolution) resolution : 8;
 
-  PTR GTY ((skip)) aux;
+  /*** Flags representing the symbol type.  ***/
+
+  /* True when symbol corresponds to a definition in current unit.
+     set via cgraph_finalize_function or varpool_finalize_decl  */
+  unsigned definition : 1;
+  /* True when symbol is an alias.  
+     Set by assemble_alias.  */
+  unsigned alias : 1;
+  /* True when alias is a weakref.  */
+  unsigned weakref : 1;
+  /* C++ frontend produce same body aliases and extra name aliases for
+     virtual functions and vtables that are obviously equivalent.
+     Those aliases are bit special, especially because C++ frontend
+     visibility code is so ugly it can not get them right at first time
+     and their visibility needs to be copied from their "masters" at
+     the end of parsing.  */
+  unsigned cpp_implicit_alias : 1;
+  /* Set once the definition was analyzed.  The list of references and
+     other properties are built during analysis.  */
+  unsigned analyzed : 1;
+
+
+  /*** Visibility and linkage flags.  ***/
+
+  /* Set when function is visible by other units.  */
+  unsigned externally_visible : 1;
+  /* The symbol will be assumed to be used in an invisible way (like
+     by an toplevel asm statement).  */
+  unsigned force_output : 1;
+  /* Like FORCE_OUTPUT, but in the case it is ABI requiring the symbol to be
+     exported.  Unlike FORCE_OUTPUT this flag gets cleared to symbols promoted
+     to static and it does not inhibit optimization.  */
+  unsigned forced_by_abi : 1;
+  /* True when the name is known to be unique and thus it does not need mangling.  */
+  unsigned unique_name : 1;
+  /* True when body and other characteristics have been removed by
+     symtab_remove_unreachable_nodes. */
+  unsigned body_removed : 1;
+
+  /*** WHOPR Partitioning flags.
+       These flags are used at ltrans stage when only part of the callgraph is
+       available. ***/
 
-  /* Set when function has address taken.
-     In current implementation it imply needed flag. */
-  unsigned address_taken : 1;
   /* Set when variable is used from other LTRANS partition.  */
   unsigned used_from_other_partition : 1;
   /* Set when function is available in the other LTRANS partition.  
      During WPA output it is used to mark nodes that are present in
      multiple partitions.  */
   unsigned in_other_partition : 1;
-  /* Set when function is visible by other units.  */
-  unsigned externally_visible : 1;
-  /* Needed variables might become dead by optimization.  This flag
-     forces the variable to be output even if it appears dead otherwise.  */
-  unsigned force_output : 1;
+
+
+
+  /*** other flags.  ***/
+
+  /* Set when symbol has address taken. */
+  unsigned address_taken : 1;
+
+
+  /* Ordering of all symtab entries.  */
+  int order;
+
+  /* Declaration representing the symbol.  */
+  tree decl;
+
+  /* Linked list of symbol table entries starting with symtab_nodes.  */
+  symtab_node *next;
+  symtab_node *previous;
+
+  /* Linked list of symbols with the same asm name.  There may be multiple
+     entries for single symbol name during LTO, because symbols are renamed
+     only after partitioning.
+
+     Because inline clones are kept in the assembler name has, they also produce
+     duplicate entries.
+
+     There are also several long standing bugs where frontends and builtin
+     code produce duplicated decls.  */
+  symtab_node *next_sharing_asm_name;
+  symtab_node *previous_sharing_asm_name;
+
+  /* Circular list of nodes in the same comdat group if non-NULL.  */
+  symtab_node *same_comdat_group;
+
+  /* Vectors of referring and referenced entities.  */
+  struct ipa_ref_list ref_list;
+
+  /* Alias target. May be either DECL pointer or ASSEMBLER_NAME pointer
+     depending to what was known to frontend on the creation time.
+     Once alias is resolved, this pointer become NULL.  */
+  tree alias_target;
+
+  /* File stream where this node is being written to.  */
+  struct lto_file_decl_data * lto_file_data;
+
+  PTR GTY ((skip)) aux;
 };
 
 enum availability
@@ -132,9 +203,6 @@ struct GTY(()) cgraph_local_info {
      and its address is never taken.  */
   unsigned local : 1;
 
-  /* Set once it has been finalized so we consider it to be output.  */
-  unsigned finalized : 1;
-
   /* False when there is something makes versioning impossible.  */
   unsigned versionable : 1;
 
@@ -182,39 +250,124 @@ struct GTY(()) ipa_replace_map
   bool ref_p;
 };
 typedef struct ipa_replace_map *ipa_replace_map_p;
-DEF_VEC_P(ipa_replace_map_p);
-DEF_VEC_ALLOC_P(ipa_replace_map_p,gc);
 
 struct GTY(()) cgraph_clone_info
 {
-  VEC(ipa_replace_map_p,gc)* tree_map;
+  vec<ipa_replace_map_p, va_gc> *tree_map;
   bitmap args_to_skip;
   bitmap combined_args_to_skip;
 };
 
+enum cgraph_simd_clone_arg_type
+{
+  SIMD_CLONE_ARG_TYPE_VECTOR,
+  SIMD_CLONE_ARG_TYPE_UNIFORM,
+  SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP,
+  SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP,
+  SIMD_CLONE_ARG_TYPE_MASK
+};
+
+/* Function arguments in the original function of a SIMD clone.
+   Supplementary data for `struct simd_clone'.  */
+
+struct GTY(()) cgraph_simd_clone_arg {
+  /* Original function argument as it originally existed in
+     DECL_ARGUMENTS.  */
+  tree orig_arg;
+
+  /* orig_arg's function (or for extern functions type from
+     TYPE_ARG_TYPES).  */
+  tree orig_type;
+
+  /* If argument is a vector, this holds the vector version of
+     orig_arg that after adjusting the argument types will live in
+     DECL_ARGUMENTS.  Otherwise, this is NULL.
+
+     This basically holds:
+       vector(simdlen) __typeof__(orig_arg) new_arg.  */
+  tree vector_arg;
+
+  /* vector_arg's type (or for extern functions new vector type.  */
+  tree vector_type;
+
+  /* If argument is a vector, this holds the array where the simd
+     argument is held while executing the simd clone function.  This
+     is a local variable in the cloned function.  Its content is
+     copied from vector_arg upon entry to the clone.
+
+     This basically holds:
+       __typeof__(orig_arg) simd_array[simdlen].  */
+  tree simd_array;
+
+  /* A SIMD clone's argument can be either linear (constant or
+     variable), uniform, or vector.  */
+  enum cgraph_simd_clone_arg_type arg_type;
+
+  /* For arg_type SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP this is
+     the constant linear step, if arg_type is
+     SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP, this is index of
+     the uniform argument holding the step, otherwise 0.  */
+  HOST_WIDE_INT linear_step;
+
+  /* Variable alignment if available, otherwise 0.  */
+  unsigned int alignment;
+};
+
+/* Specific data for a SIMD function clone.  */
+
+struct GTY(()) cgraph_simd_clone {
+  /* Number of words in the SIMD lane associated with this clone.  */
+  unsigned int simdlen;
+
+  /* Number of annotated function arguments in `args'.  This is
+     usually the number of named arguments in FNDECL.  */
+  unsigned int nargs;
+
+  /* Max hardware vector size in bits for integral vectors.  */
+  unsigned int vecsize_int;
+
+  /* Max hardware vector size in bits for floating point vectors.  */
+  unsigned int vecsize_float;
+
+  /* The mangling character for a given vector size.  This is is used
+     to determine the ISA mangling bit as specified in the Intel
+     Vector ABI.  */
+  unsigned char vecsize_mangle;
+
+  /* True if this is the masked, in-branch version of the clone,
+     otherwise false.  */
+  unsigned int inbranch : 1;
+
+  /* True if this is a Cilk Plus variant.  */
+  unsigned int cilk_elemental : 1;
+
+  /* Doubly linked list of SIMD clones.  */
+  struct cgraph_node *prev_clone, *next_clone;
+
+  /* Original cgraph node the SIMD clones were created for.  */
+  struct cgraph_node *origin;
+
+  /* Annotated function arguments for the original function.  */
+  struct cgraph_simd_clone_arg GTY((length ("%h.nargs"))) args[1];
+};
+
 
 /* The cgraph data structure.
    Each function decl has assigned cgraph_node listing callees and callers.  */
 
-struct GTY(()) cgraph_node {
-  struct symtab_node_base symbol;
+struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node {
+public:
   struct cgraph_edge *callees;
   struct cgraph_edge *callers;
   /* List of edges representing indirect calls with a yet undetermined
      callee.  */
   struct cgraph_edge *indirect_calls;
   /* For nested functions points to function the node is nested in.  */
-  struct cgraph_node *
-    GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h")))
-    origin;
+  struct cgraph_node *origin;
   /* Points to first nested function, if any.  */
-  struct cgraph_node *
-    GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h")))
-    nested;
+  struct cgraph_node *nested;
   /* Pointer to the next function with same origin, if any.  */
-  struct cgraph_node *
-    GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h")))
-    next_nested;
+  struct cgraph_node *next_nested;
   /* Pointer to the next clone.  */
   struct cgraph_node *next_sibling_clone;
   struct cgraph_node *prev_sibling_clone;
@@ -226,10 +379,16 @@ struct GTY(()) cgraph_node {
   /* Declaration node used to be clone of. */
   tree former_clone_of;
 
+  /* If this is a SIMD clone, this points to the SIMD specific
+     information for it.  */
+  struct cgraph_simd_clone *simdclone;
+  /* If this function has SIMD clones, this points to the first clone.  */
+  struct cgraph_node *simd_clones;
+
   /* Interprocedural passes scheduled to have their transform functions
      applied next time we execute local pass on them.  We maintain it
      per-function in order to allow IPA passes to introduce new functions.  */
-  VEC(ipa_opt_pass,heap) * GTY((skip)) ipa_transforms_to_apply;
+  vec<ipa_opt_pass> GTY((skip)) ipa_transforms_to_apply;
 
   struct cgraph_local_info local;
   struct cgraph_global_info global;
@@ -244,21 +403,19 @@ struct GTY(()) cgraph_node {
   int count_materialization_scale;
   /* Unique id of the node.  */
   int uid;
+  /* ID assigned by the profiling.  */
+  unsigned int profile_id;
+  /* Time profiler: first run of function.  */
+  int tp_first_run;
 
   /* Set when decl is an abstract function pointed to by the
      ABSTRACT_DECL_ORIGIN of a reachable function.  */
-  unsigned abstract_and_needed : 1;
+  unsigned used_as_abstract_origin : 1;
   /* Set once the function is lowered (i.e. its CFG is built).  */
   unsigned lowered : 1;
   /* Set once the function has been instantiated and its callee
      lists created.  */
-  unsigned analyzed : 1;
-  /* Set when function is scheduled to be processed by local passes.  */
   unsigned process : 1;
-  /* Set for aliases once they got through assemble_alias.  */
-  unsigned alias : 1;
-  /* Set for aliases created as C++ same body aliases.  */
-  unsigned same_body_alias : 1;
   /* How commonly executed the node is.  Initialized during branch
      probabilities pass.  */
   ENUM_BITFIELD (node_frequency) frequency : 2;
@@ -271,88 +428,146 @@ struct GTY(()) cgraph_node {
   /* ?? We should be able to remove this.  We have enough bits in
      cgraph to calculate it.  */
   unsigned tm_clone : 1;
+  /* True if this decl is a dispatcher for function versions.  */
+  unsigned dispatcher_function : 1;
+  /* True if this decl calls a COMDAT-local function.  This is set up in
+     compute_inline_parameters and inline_call.  */
+  unsigned calls_comdat_local : 1;
 };
 
+
 typedef struct cgraph_node *cgraph_node_ptr;
 
-DEF_VEC_P(cgraph_node_ptr);
-DEF_VEC_ALLOC_P(cgraph_node_ptr,heap);
-DEF_VEC_ALLOC_P(cgraph_node_ptr,gc);
+
+/* Function Multiversioning info.  */
+struct GTY(()) cgraph_function_version_info {
+  /* The cgraph_node for which the function version info is stored.  */
+  struct cgraph_node *this_node;
+  /* Chains all the semantically identical function versions.  The
+     first function in this chain is the version_info node of the
+     default function.  */
+  struct cgraph_function_version_info *prev;
+  /* If this version node corresponds to a dispatcher for function
+     versions, this points to the version info node of the default
+     function, the first node in the chain.  */
+  struct cgraph_function_version_info *next;
+  /* If this node corresponds to a function version, this points
+     to the dispatcher function decl, which is the function that must
+     be called to execute the right function version at run-time.
+
+     If this cgraph node is a dispatcher (if dispatcher_function is
+     true, in the cgraph_node struct) for function versions, this
+     points to resolver function, which holds the function body of the
+     dispatcher. The dispatcher decl is an alias to the resolver
+     function decl.  */
+  tree dispatcher_resolver;
+};
+
+/* Get the cgraph_function_version_info node corresponding to node.  */
+struct cgraph_function_version_info *
+  get_cgraph_node_version (struct cgraph_node *node);
+
+/* Insert a new cgraph_function_version_info node into cgraph_fnver_htab
+   corresponding to cgraph_node NODE.  */
+struct cgraph_function_version_info *
+  insert_new_cgraph_node_version (struct cgraph_node *node);
+
+/* Record that DECL1 and DECL2 are semantically identical function
+   versions.  */
+void record_function_versions (tree decl1, tree decl2);
+
+/* Remove the cgraph_function_version_info and cgraph_node for DECL.  This
+   DECL is a duplicate declaration.  */
+void delete_function_version (tree decl);
 
 /* A cgraph node set is a collection of cgraph nodes.  A cgraph node
    can appear in multiple sets.  */
 struct cgraph_node_set_def
 {
   struct pointer_map_t *map;
-  VEC(cgraph_node_ptr, heap) *nodes;
+  vec<cgraph_node_ptr> nodes;
 };
 
-typedef struct varpool_node *varpool_node_ptr;
+class varpool_node;
+typedef varpool_node *varpool_node_ptr;
 
-DEF_VEC_P(varpool_node_ptr);
-DEF_VEC_ALLOC_P(varpool_node_ptr,heap);
-DEF_VEC_ALLOC_P(varpool_node_ptr,gc);
 
 /* A varpool node set is a collection of varpool nodes.  A varpool node
    can appear in multiple sets.  */
 struct varpool_node_set_def
 {
   struct pointer_map_t * map;
-  VEC(varpool_node_ptr, heap) *nodes;
+  vec<varpool_node_ptr> nodes;
 };
 
 typedef struct cgraph_node_set_def *cgraph_node_set;
 
-DEF_VEC_P(cgraph_node_set);
-DEF_VEC_ALLOC_P(cgraph_node_set,gc);
-DEF_VEC_ALLOC_P(cgraph_node_set,heap);
 
 typedef struct varpool_node_set_def *varpool_node_set;
 
-DEF_VEC_P(varpool_node_set);
-DEF_VEC_ALLOC_P(varpool_node_set,gc);
-DEF_VEC_ALLOC_P(varpool_node_set,heap);
 
 /* Iterator structure for cgraph node sets.  */
-typedef struct
+struct cgraph_node_set_iterator
 {
   cgraph_node_set set;
   unsigned index;
-} cgraph_node_set_iterator;
+};
 
 /* Iterator structure for varpool node sets.  */
-typedef struct
+struct varpool_node_set_iterator
 {
   varpool_node_set set;
   unsigned index;
-} varpool_node_set_iterator;
+};
 
-#define DEFCIFCODE(code, string)       CIF_ ## code,
+#define DEFCIFCODE(code, type, string) CIF_ ## code,
 /* Reasons for inlining failures.  */
-typedef enum cgraph_inline_failed_enum {
+enum cgraph_inline_failed_t {
 #include "cif-code.def"
   CIF_N_REASONS
-} cgraph_inline_failed_t;
+};
+
+enum cgraph_inline_failed_type_t
+{
+  CIF_FINAL_NORMAL = 0,
+  CIF_FINAL_ERROR
+};
 
 /* Structure containing additional information about an indirect call.  */
 
 struct GTY(()) cgraph_indirect_call_info
 {
-  /* Offset accumulated from ancestor jump functions of inlined call graph
-     edges.  */
-  HOST_WIDE_INT anc_offset;
+  /* When polymorphic is set, this field contains offset where the object which
+     was actually used in the polymorphic resides within a larger structure.
+     If agg_contents is set, the field contains the offset within the aggregate
+     from which the address to call was loaded.  */
+  HOST_WIDE_INT offset;
   /* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set).  */
   HOST_WIDE_INT otr_token;
   /* Type of the object from OBJ_TYPE_REF_OBJECT. */
-  tree otr_type;
+  tree otr_type, outer_type;
   /* Index of the parameter that is called.  */
   int param_index;
   /* ECF flags determined from the caller.  */
   int ecf_flags;
+  /* Profile_id of common target obtrained from profile.  */
+  int common_target_id;
+  /* Probability that call will land in function with COMMON_TARGET_ID.  */
+  int common_target_probability;
 
   /* Set when the call is a virtual call with the parameter being the
      associated object pointer rather than a simple direct call.  */
   unsigned polymorphic : 1;
+  /* Set when the call is a call of a pointer loaded from contents of an
+     aggregate at offset.  */
+  unsigned agg_contents : 1;
+  /* Set when this is a call through a member pointer.  */
+  unsigned member_ptr : 1;
+  /* When the previous bit is set, this one determines whether the destination
+     is loaded from a parameter passed by reference. */
+  unsigned by_ref : 1;
+  unsigned int maybe_in_construction : 1;
+  unsigned int maybe_derived_type : 1;
 };
 
 struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgraph_edge {
@@ -371,7 +586,7 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgrap
   PTR GTY ((skip (""))) aux;
   /* When equal to CIF_OK, inline this call.  Otherwise, points to the
      explanation why function was not inlined.  */
-  cgraph_inline_failed_t inline_failed;
+  enum cgraph_inline_failed_t inline_failed;
   /* The stmt_uid of call_stmt.  This is used by LTO to recover the call_stmt
      when the function is serialized in.  */
   unsigned int lto_stmt_uid;
@@ -391,6 +606,24 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgrap
   unsigned int call_stmt_cannot_inline_p : 1;
   /* Can this call throw externally?  */
   unsigned int can_throw_external : 1;
+  /* Edges with SPECULATIVE flag represents indirect calls that was
+     speculatively turned into direct (i.e. by profile feedback).
+     The final code sequence will have form:
+
+     if (call_target == expected_fn)
+       expected_fn ();
+     else
+       call_target ();
+
+     Every speculative call is represented by three components attached
+     to a same call statement:
+     1) a direct call (to expected_fn)
+     2) an indirect call (to call_target)
+     3) a IPA_REF_ADDR refrence to expected_fn.
+
+     Optimizers may later redirect direct call to clone, so 1) and 3)
+     do not need to necesarily agree with destination.  */
+  unsigned int speculative : 1;
 };
 
 #define CGRAPH_FREQ_BASE 1000
@@ -398,28 +631,18 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgrap
 
 typedef struct cgraph_edge *cgraph_edge_p;
 
-DEF_VEC_P(cgraph_edge_p);
-DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
 
 /* The varpool data structure.
    Each static variable decl has assigned varpool_node.  */
 
-struct GTY(()) varpool_node {
-  struct symtab_node_base symbol;
-  /* For aliases points to declaration DECL is alias of.  */
-  tree alias_of;
-
-  /* Set once the variable has been instantiated and its callee
-     lists created.  */
-  unsigned analyzed : 1;
-  /* Set once it has been finalized so we consider it to be output.  */
-  unsigned finalized : 1;
+class GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node {
+public:
   /* Set when variable is scheduled to be assembled.  */
   unsigned output : 1;
-  /* Set for aliases once they got through assemble_alias.  Also set for
-     extra name aliases in varpool_extra_name_alias.  */
-  unsigned alias : 1;
-  unsigned extra_name_alias : 1;
+
+  /* Set if the variable is dynamically initialized, except for
+     function local statics.   */
+  unsigned dynamically_initialized : 1;
 };
 
 /* Every top level asm statement is put into a asm_node.  */
@@ -433,17 +656,27 @@ struct GTY(()) asm_node {
   int order;
 };
 
-/* Symbol table entry.  */
-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.  */
-  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 *p)
+{
+  return p->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 *p)
+{
+  return p->type == SYMTAB_VARIABLE;
+}
 
-extern GTY(()) symtab_node symtab_nodes;
+extern GTY(()) symtab_node *symtab_nodes;
 extern GTY(()) int cgraph_n_nodes;
 extern GTY(()) int cgraph_max_uid;
 extern GTY(()) int cgraph_edge_max_uid;
@@ -454,6 +687,8 @@ enum cgraph_state
   CGRAPH_STATE_PARSING,
   /* Callgraph is being constructed.  It is safe to add new functions.  */
   CGRAPH_STATE_CONSTRUCTION,
+  /* Callgraph is being at LTO time.  */
+  CGRAPH_LTO_STREAMING,
   /* Callgraph is built and IPA passes are being run.  */
   CGRAPH_STATE_IPA,
   /* Callgraph is built and all functions are transformed to SSA form.  */
@@ -469,29 +704,53 @@ extern cgraph_node_set cgraph_new_nodes;
 
 extern GTY(()) struct asm_node *asm_nodes;
 extern GTY(()) int symtab_order;
-extern bool same_body_aliases_done;
+extern bool cpp_implicit_aliases_done;
+
+/* Classifcation of symbols WRT partitioning.  */
+enum symbol_partitioning_class
+{
+   /* External declarations are ignored by partitioning algorithms and they are
+      added into the boundary later via compute_ltrans_boundary.  */
+   SYMBOL_EXTERNAL,
+   /* Partitioned symbols are pur into one of partitions.  */
+   SYMBOL_PARTITION,
+   /* Duplicated symbols (such as comdat or constant pool references) are
+      copied into every node needing them via add_symbol_to_partition.  */
+   SYMBOL_DUPLICATE
+};
+
 
 /* In symtab.c  */
-void symtab_register_node (symtab_node);
-void symtab_unregister_node (symtab_node);
-void symtab_remove_node (symtab_node);
-symtab_node symtab_get_node (const_tree);
-symtab_node symtab_node_for_asm (const_tree asmname);
-const char * symtab_node_asm_name (symtab_node);
-const char * symtab_node_name (symtab_node);
-void symtab_insert_node_to_hashtable (symtab_node);
-void symtab_add_to_same_comdat_group (symtab_node, symtab_node);
-void symtab_dissolve_same_comdat_group_list (symtab_node node);
+void symtab_register_node (symtab_node *);
+void symtab_unregister_node (symtab_node *);
+void symtab_remove_node (symtab_node *);
+symtab_node *symtab_get_node (const_tree);
+symtab_node *symtab_node_for_asm (const_tree asmname);
+void symtab_insert_node_to_hashtable (symtab_node *);
+void symtab_add_to_same_comdat_group (symtab_node *, symtab_node *);
+void symtab_dissolve_same_comdat_group_list (symtab_node *node);
 void dump_symtab (FILE *);
 void debug_symtab (void);
-void dump_symtab_node (FILE *, symtab_node);
-void debug_symtab_node (symtab_node);
-void dump_symtab_base (FILE *, symtab_node);
+void dump_symtab_node (FILE *, symtab_node *);
+void debug_symtab_node (symtab_node *);
+void dump_symtab_base (FILE *, symtab_node *);
 void verify_symtab (void);
-void verify_symtab_node (symtab_node);
-bool verify_symtab_base (symtab_node);
-bool symtab_used_from_object_file_p (symtab_node);
+void verify_symtab_node (symtab_node *);
+bool verify_symtab_base (symtab_node *);
+bool symtab_used_from_object_file_p (symtab_node *);
 void symtab_make_decl_local (tree);
+symtab_node *symtab_alias_ultimate_target (symtab_node *,
+                                         enum availability *avail = NULL);
+bool symtab_resolve_alias (symtab_node *node, symtab_node *target);
+void fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target);
+bool symtab_for_node_and_aliases (symtab_node *,
+                                 bool (*) (symtab_node *, void *),
+                                 void *,
+                                 bool);
+symtab_node *symtab_nonoverwritable_alias (symtab_node *);
+enum availability symtab_node_availability (symtab_node *);
+bool symtab_semantically_equivalent_p (symtab_node *, symtab_node *);
+enum symbol_partitioning_class symtab_get_symbol_partitioning_class (symtab_node *);
 
 /* In cgraph.c  */
 void dump_cgraph (FILE *);
@@ -501,6 +760,7 @@ void debug_cgraph_node (struct cgraph_node *);
 void cgraph_remove_edge (struct cgraph_edge *);
 void cgraph_remove_node (struct cgraph_node *);
 void cgraph_release_function_body (struct cgraph_node *);
+void release_function_body (tree);
 void cgraph_node_remove_callees (struct cgraph_node *node);
 struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
                                        struct cgraph_node *,
@@ -516,7 +776,7 @@ struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, H
                                       HOST_WIDE_INT, tree, tree);
 struct cgraph_node *cgraph_node_for_asm (tree);
 struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);
-void cgraph_set_call_stmt (struct cgraph_edge *, gimple);
+void cgraph_set_call_stmt (struct cgraph_edge *, gimple, bool update_speculative = true);
 void cgraph_update_edges_for_call_stmt (gimple, tree, gimple);
 struct cgraph_local_info *cgraph_local_info (tree);
 struct cgraph_global_info *cgraph_global_info (tree);
@@ -528,7 +788,7 @@ void cgraph_call_edge_duplication_hooks (struct cgraph_edge *,
                                         struct cgraph_edge *);
 
 void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
-void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *);
+struct cgraph_edge *cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *);
 bool cgraph_only_called_directly_p (struct cgraph_node *);
 
 bool cgraph_function_possibly_inlined_p (tree);
@@ -537,6 +797,7 @@ void cgraph_unnest_node (struct cgraph_node *);
 enum availability cgraph_function_body_availability (struct cgraph_node *);
 void cgraph_add_new_function (tree, bool);
 const char* cgraph_inline_failed_string (cgraph_inline_failed_t);
+cgraph_inline_failed_type_t cgraph_inline_failed_type (cgraph_inline_failed_t);
 
 void cgraph_set_nothrow_flag (struct cgraph_node *, bool);
 void cgraph_set_const_flag (struct cgraph_node *, bool, bool);
@@ -556,19 +817,21 @@ bool cgraph_for_node_thunks_and_aliases (struct cgraph_node *,
 bool cgraph_for_node_and_aliases (struct cgraph_node *,
                                  bool (*) (struct cgraph_node *, void *),
                                  void *, bool);
-VEC (cgraph_edge_p, heap) * collect_callers_of_node (struct cgraph_node *node);
+vec<cgraph_edge_p>  collect_callers_of_node (struct cgraph_node *node);
 void verify_cgraph (void);
 void verify_cgraph_node (struct cgraph_node *);
 void cgraph_mark_address_taken_node (struct cgraph_node *);
 
 typedef void (*cgraph_edge_hook)(struct cgraph_edge *, void *);
 typedef void (*cgraph_node_hook)(struct cgraph_node *, void *);
+typedef void (*varpool_node_hook)(varpool_node *, void *);
 typedef void (*cgraph_2edge_hook)(struct cgraph_edge *, struct cgraph_edge *,
                                  void *);
 typedef void (*cgraph_2node_hook)(struct cgraph_node *, struct cgraph_node *,
                                  void *);
 struct cgraph_edge_hook_list;
 struct cgraph_node_hook_list;
+struct varpool_node_hook_list;
 struct cgraph_2edge_hook_list;
 struct cgraph_2node_hook_list;
 struct cgraph_edge_hook_list *cgraph_add_edge_removal_hook (cgraph_edge_hook, void *);
@@ -576,16 +839,33 @@ void cgraph_remove_edge_removal_hook (struct cgraph_edge_hook_list *);
 struct cgraph_node_hook_list *cgraph_add_node_removal_hook (cgraph_node_hook,
                                                            void *);
 void cgraph_remove_node_removal_hook (struct cgraph_node_hook_list *);
+struct varpool_node_hook_list *varpool_add_node_removal_hook (varpool_node_hook,
+                                                             void *);
+void varpool_remove_node_removal_hook (struct varpool_node_hook_list *);
 struct cgraph_node_hook_list *cgraph_add_function_insertion_hook (cgraph_node_hook,
                                                                  void *);
 void cgraph_remove_function_insertion_hook (struct cgraph_node_hook_list *);
+struct varpool_node_hook_list *varpool_add_variable_insertion_hook (varpool_node_hook,
+                                                                   void *);
+void varpool_remove_variable_insertion_hook (struct varpool_node_hook_list *);
 void cgraph_call_function_insertion_hooks (struct cgraph_node *node);
 struct cgraph_2edge_hook_list *cgraph_add_edge_duplication_hook (cgraph_2edge_hook, void *);
 void cgraph_remove_edge_duplication_hook (struct cgraph_2edge_hook_list *);
 struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_hook, void *);
 void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *);
 gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *);
-bool cgraph_propagate_frequency (struct cgraph_node *node);
+struct cgraph_node * cgraph_function_node (struct cgraph_node *,
+                                          enum availability *avail = NULL);
+bool cgraph_get_body (struct cgraph_node *node);
+struct cgraph_edge *
+cgraph_turn_edge_to_speculative (struct cgraph_edge *,
+                                struct cgraph_node *,
+                                gcov_type, int);
+void cgraph_speculative_call_info (struct cgraph_edge *,
+                                  struct cgraph_edge *&,
+                                  struct cgraph_edge *&,
+                                  struct ipa_ref *&);
+extern bool gimple_check_call_matching_types (gimple, tree, bool);
 
 /* In cgraphunit.c  */
 struct asm_node *add_asm_node (tree);
@@ -594,9 +874,14 @@ void cgraph_finalize_function (tree, bool);
 void finalize_compilation_unit (void);
 void compile (void);
 void init_cgraph (void);
-bool cgraph_process_new_functions (void);
+void cgraph_process_new_functions (void);
 void cgraph_process_same_body_aliases (void);
-void fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alias);
+void fixup_same_cpp_alias_visibility (symtab_node *, symtab_node *target, tree);
+/*  Initialize datastructures so DECL is a function in lowered gimple form.
+    IN_SSA is true if the gimple is in SSA.  */
+basic_block init_lowered_empty_function (tree, bool);
+void cgraph_reset_node (struct cgraph_node *);
+bool expand_thunk (struct cgraph_node *, bool);
 
 /* In cgraphclones.c  */
 
@@ -604,37 +889,40 @@ struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *,
                                        struct cgraph_node *, gimple,
                                        unsigned, gcov_type, int, bool);
 struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type,
-                                       int, bool, VEC(cgraph_edge_p,heap) *,
-                                       bool);
+                                       int, bool, vec<cgraph_edge_p>,
+                                       bool, struct cgraph_node *);
 tree clone_function_name (tree decl, const char *);
 struct cgraph_node * cgraph_create_virtual_clone (struct cgraph_node *old_node,
-                                                 VEC(cgraph_edge_p,heap)*,
-                                                 VEC(ipa_replace_map_p,gc)* tree_map,
+                                                 vec<cgraph_edge_p>,
+                                                 vec<ipa_replace_map_p, va_gc> *tree_map,
                                                  bitmap args_to_skip,
                                                  const char *clone_name);
 struct cgraph_node *cgraph_find_replacement_node (struct cgraph_node *);
 bool cgraph_remove_node_and_inline_clones (struct cgraph_node *, struct cgraph_node *);
-void cgraph_set_call_stmt_including_clones (struct cgraph_node *, gimple, gimple);
+void cgraph_set_call_stmt_including_clones (struct cgraph_node *, gimple, gimple,
+                                           bool update_speculative = true);
 void cgraph_create_edge_including_clones (struct cgraph_node *,
                                          struct cgraph_node *,
                                          gimple, gimple, gcov_type, int,
                                          cgraph_inline_failed_t);
 void cgraph_materialize_all_clones (void);
 struct cgraph_node * cgraph_copy_node_for_versioning (struct cgraph_node *,
-               tree, VEC(cgraph_edge_p,heap)*, bitmap);
+               tree, vec<cgraph_edge_p>, bitmap);
 struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
-                                               VEC(cgraph_edge_p,heap)*,
-                                               VEC(ipa_replace_map_p,gc)*,
+                                               vec<cgraph_edge_p>,
+                                               vec<ipa_replace_map_p, va_gc> *,
                                                bitmap, bool, bitmap,
                                                basic_block, const char *);
-void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*,
+void tree_function_versioning (tree, tree, vec<ipa_replace_map_p, va_gc> *,
                               bool, bitmap, bool, bitmap, basic_block);
+struct cgraph_edge *cgraph_resolve_speculation (struct cgraph_edge *, tree);
 
 /* In cgraphbuild.c  */
 unsigned int rebuild_cgraph_edges (void);
 void cgraph_rebuild_references (void);
 int compute_call_stmt_bb_frequency (tree, basic_block bb);
 void record_references_in_initializer (tree, bool);
+void ipa_record_stmt_references (struct cgraph_node *, gimple);
 
 /* In ipa.c  */
 bool symtab_remove_unreachable_nodes (bool, FILE *);
@@ -650,77 +938,68 @@ void cgraph_build_static_cdtor (char which, tree body, int priority);
 
 varpool_node_set varpool_node_set_new (void);
 varpool_node_set_iterator varpool_node_set_find (varpool_node_set,
-                                              struct varpool_node *);
-void varpool_node_set_add (varpool_node_set, struct varpool_node *);
-void varpool_node_set_remove (varpool_node_set, struct varpool_node *);
+                                                varpool_node *);
+void varpool_node_set_add (varpool_node_set, varpool_node *);
+void varpool_node_set_remove (varpool_node_set, varpool_node *);
 void dump_varpool_node_set (FILE *, varpool_node_set);
 void debug_varpool_node_set (varpool_node_set);
 void free_varpool_node_set (varpool_node_set);
 void ipa_discover_readonly_nonaddressable_vars (void);
-bool cgraph_comdat_can_be_unshared_p (struct cgraph_node *);
-bool varpool_externally_visible_p (struct varpool_node *, bool);
+bool varpool_externally_visible_p (varpool_node *);
 
 /* In predict.c  */
 bool cgraph_maybe_hot_edge_p (struct cgraph_edge *e);
 bool cgraph_optimize_for_size_p (struct cgraph_node *);
 
 /* In varpool.c  */
-struct varpool_node *varpool_node (tree);
-struct varpool_node *varpool_node_for_asm (tree asmname);
-void varpool_mark_needed_node (struct varpool_node *);
+varpool_node *varpool_create_empty_node (void);
+varpool_node *varpool_node_for_decl (tree);
+varpool_node *varpool_node_for_asm (tree asmname);
+void varpool_mark_needed_node (varpool_node *);
 void debug_varpool (void);
 void dump_varpool (FILE *);
-void dump_varpool_node (FILE *, struct varpool_node *);
+void dump_varpool_node (FILE *, varpool_node *);
 
 void varpool_finalize_decl (tree);
-bool decide_is_variable_needed (struct varpool_node *, tree);
-enum availability cgraph_variable_initializer_availability (struct varpool_node *);
+enum availability cgraph_variable_initializer_availability (varpool_node *);
 void cgraph_make_node_local (struct cgraph_node *);
 bool cgraph_node_can_be_local_p (struct cgraph_node *);
 
 
-void varpool_remove_node (struct varpool_node *node);
-void varpool_finalize_named_section_flags (struct varpool_node *node);
+void varpool_remove_node (varpool_node *node);
+void varpool_finalize_named_section_flags (varpool_node *node);
 bool varpool_output_variables (void);
-bool varpool_assemble_decl (struct varpool_node *node);
-void varpool_analyze_node (struct varpool_node *);
-struct varpool_node * varpool_extra_name_alias (tree, tree);
-struct varpool_node * varpool_create_variable_alias (tree, tree);
+bool varpool_assemble_decl (varpool_node *node);
+void varpool_analyze_node (varpool_node *);
+varpool_node * varpool_extra_name_alias (tree, tree);
+varpool_node * varpool_create_variable_alias (tree, tree);
 void varpool_reset_queue (void);
-bool const_value_known_p (tree);
-bool varpool_for_node_and_aliases (struct varpool_node *,
-                                  bool (*) (struct varpool_node *, void *),
+tree ctor_for_folding (tree);
+bool varpool_for_node_and_aliases (varpool_node *,
+                                  bool (*) (varpool_node *, void *),
                                   void *, bool);
 void varpool_add_new_variable (tree);
+void symtab_initialize_asm_name_hash (void);
+void symtab_prevail_in_asm_name_hash (symtab_node *node);
+void varpool_remove_initializer (varpool_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;
-}
+/* In cgraph.c */
+extern void change_decl_assembler_name (tree, tree);
 
 /* Return callgraph node for given symbol and check it is a function. */
 static inline struct cgraph_node *
-cgraph (symtab_node node)
+cgraph (symtab_node *node)
 {
-  gcc_checking_assert (!node || node->symbol.type == SYMTAB_FUNCTION);
+  gcc_checking_assert (!node || node->type == SYMTAB_FUNCTION);
   return (struct cgraph_node *)node;
 }
 
 /* Return varpool node for given symbol and check it is a variable.  */
-static inline struct varpool_node *
-varpool (symtab_node node)
+static inline varpool_node *
+varpool (symtab_node *node)
 {
-  gcc_checking_assert (!node || node->symbol.type == SYMTAB_VARIABLE);
-  return (struct varpool_node *)node;
+  gcc_checking_assert (!node || node->type == SYMTAB_VARIABLE);
+  return (varpool_node *)node;
 }
 
 /* Return callgraph node for given symbol and check it is a function. */
@@ -732,69 +1011,37 @@ cgraph_get_node (const_tree decl)
 }
 
 /* Return varpool node for given symbol and check it is a function. */
-static inline struct varpool_node *
+static inline varpool_node *
 varpool_get_node (const_tree decl)
 {
   gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
   return varpool (symtab_get_node (decl));
 }
 
-/* Return asm name of cgraph node.  */
-static inline const char *
-cgraph_node_asm_name(struct cgraph_node *node)
-{
-  return symtab_node_asm_name ((symtab_node)node);
-}
-
-/* Return asm name of varpool node.  */
-static inline const char *
-varpool_node_asm_name(struct varpool_node *node)
-{
-  return symtab_node_asm_name ((symtab_node)node);
-}
-
-/* Return name of cgraph node.  */
-static inline const char *
-cgraph_node_name(struct cgraph_node *node)
-{
-  return symtab_node_name ((symtab_node)node);
-}
-
-/* Return name of varpool node.  */
-static inline const char *
-varpool_node_name(struct varpool_node *node)
-{
-  return symtab_node_name ((symtab_node)node);
-}
-
 /* Walk all symbols.  */
 #define FOR_EACH_SYMBOL(node) \
-   for ((node) = symtab_nodes; (node); (node) = (node)->symbol.next)
+   for ((node) = symtab_nodes; (node); (node) = (node)->next)
 
 
 /* Return first variable.  */
-static inline struct varpool_node *
+static inline varpool_node *
 varpool_first_variable (void)
 {
-  symtab_node node;
-  for (node = symtab_nodes; node; node = node->symbol.next)
-    {
-      if (symtab_variable_p (node))
-       return varpool (node);
-    }
+  symtab_node *node;
+  for (node = symtab_nodes; node; node = node->next)
+    if (varpool_node *vnode = dyn_cast <varpool_node> (node))
+      return vnode;
   return NULL;
 }
 
 /* Return next variable after NODE.  */
-static inline struct varpool_node *
-varpool_next_variable (struct varpool_node *node)
+static inline varpool_node *
+varpool_next_variable (varpool_node *node)
 {
-  symtab_node node1 = (symtab_node) node->symbol.next;
-  for (; node1; node1 = node1->symbol.next)
-    {
-      if (symtab_variable_p (node1))
-       return varpool (node1);
-    }
+  symtab_node *node1 = node->next;
+  for (; node1; node1 = node1->next)
+    if (varpool_node *vnode1 = dyn_cast <varpool_node> (node1))
+      return vnode1;
   return NULL;
 }
 /* Walk all variables.  */
@@ -804,29 +1051,29 @@ varpool_next_variable (struct varpool_node *node)
        (node) = varpool_next_variable ((node)))
 
 /* Return first reachable static variable with initializer.  */
-static inline struct varpool_node *
+static inline varpool_node *
 varpool_first_static_initializer (void)
 {
-  symtab_node node;
-  for (node = symtab_nodes; node; node = node->symbol.next)
+  symtab_node *node;
+  for (node = symtab_nodes; node; node = node->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->decl))
+       return vnode;
     }
   return NULL;
 }
 
 /* Return next reachable static variable with initializer after NODE.  */
-static inline struct varpool_node *
-varpool_next_static_initializer (struct varpool_node *node)
+static inline varpool_node *
+varpool_next_static_initializer (varpool_node *node)
 {
-  symtab_node node1 = (symtab_node) node->symbol.next;
-  for (; node1; node1 = node1->symbol.next)
+  symtab_node *node1 = node->next;
+  for (; node1; node1 = node1->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->decl))
+       return vnode1;
     }
   return NULL;
 }
@@ -837,27 +1084,29 @@ varpool_next_static_initializer (struct varpool_node *node)
         (node) = varpool_next_static_initializer (node))
 
 /* Return first reachable static variable with initializer.  */
-static inline struct varpool_node *
+static inline varpool_node *
 varpool_first_defined_variable (void)
 {
-  symtab_node node;
-  for (node = symtab_nodes; node; node = node->symbol.next)
+  symtab_node *node;
+  for (node = symtab_nodes; node; node = node->next)
     {
-      if (symtab_variable_p (node) && varpool (node)->analyzed)
-       return varpool (node);
+      varpool_node *vnode = dyn_cast <varpool_node> (node);
+      if (vnode && vnode->definition)
+       return vnode;
     }
   return NULL;
 }
 
 /* Return next reachable static variable with initializer after NODE.  */
-static inline struct varpool_node *
-varpool_next_defined_variable (struct varpool_node *node)
+static inline varpool_node *
+varpool_next_defined_variable (varpool_node *node)
 {
-  symtab_node node1 = (symtab_node) node->symbol.next;
-  for (; node1; node1 = node1->symbol.next)
+  symtab_node *node1 = node->next;
+  for (; node1; node1 = node1->next)
     {
-      if (symtab_variable_p (node1) && varpool (node1)->analyzed)
-       return varpool (node1);
+      varpool_node *vnode1 = dyn_cast <varpool_node> (node1);
+      if (vnode1 && vnode1->definition)
+       return vnode1;
     }
   return NULL;
 }
@@ -870,11 +1119,12 @@ varpool_next_defined_variable (struct varpool_node *node)
 static inline struct cgraph_node *
 cgraph_first_defined_function (void)
 {
-  symtab_node node;
-  for (node = symtab_nodes; node; node = node->symbol.next)
+  symtab_node *node;
+  for (node = symtab_nodes; node; node = node->next)
     {
-      if (symtab_function_p (node) && cgraph (node)->analyzed)
-       return cgraph (node);
+      cgraph_node *cn = dyn_cast <cgraph_node> (node);
+      if (cn && cn->definition)
+       return cn;
     }
   return NULL;
 }
@@ -883,11 +1133,12 @@ cgraph_first_defined_function (void)
 static inline struct cgraph_node *
 cgraph_next_defined_function (struct cgraph_node *node)
 {
-  symtab_node node1 = (symtab_node) node->symbol.next;
-  for (; node1; node1 = node1->symbol.next)
+  symtab_node *node1 = node->next;
+  for (; node1; node1 = node1->next)
     {
-      if (symtab_function_p (node1) && cgraph (node1)->analyzed)
-       return cgraph (node1);
+      cgraph_node *cn1 = dyn_cast <cgraph_node> (node1);
+      if (cn1 && cn1->definition)
+       return cn1;
     }
   return NULL;
 }
@@ -901,12 +1152,10 @@ cgraph_next_defined_function (struct cgraph_node *node)
 static inline struct cgraph_node *
 cgraph_first_function (void)
 {
-  symtab_node node;
-  for (node = symtab_nodes; node; node = node->symbol.next)
-    {
-      if (symtab_function_p (node))
-       return cgraph (node);
-    }
+  symtab_node *node;
+  for (node = symtab_nodes; node; node = node->next)
+    if (cgraph_node *cn = dyn_cast <cgraph_node> (node))
+      return cn;
   return NULL;
 }
 
@@ -914,12 +1163,10 @@ cgraph_first_function (void)
 static inline struct cgraph_node *
 cgraph_next_function (struct cgraph_node *node)
 {
-  symtab_node node1 = (symtab_node) node->symbol.next;
-  for (; node1; node1 = node1->symbol.next)
-    {
-      if (symtab_function_p (node1))
-       return cgraph (node1);
-    }
+  symtab_node *node1 = node->next;
+  for (; node1; node1 = node1->next)
+    if (cgraph_node *cn1 = dyn_cast <cgraph_node> (node1))
+      return cn1;
   return NULL;
 }
 /* Walk all functions.  */
@@ -936,19 +1183,19 @@ cgraph_next_function (struct cgraph_node *node)
 static inline bool
 cgraph_function_with_gimple_body_p (struct cgraph_node *node)
 {
-  return node->analyzed && !node->thunk.thunk_p && !node->alias;
+  return node->definition && !node->thunk.thunk_p && !node->alias;
 }
 
 /* Return first function with body defined.  */
 static inline struct cgraph_node *
 cgraph_first_function_with_gimple_body (void)
 {
-  symtab_node node;
-  for (node = symtab_nodes; node; node = node->symbol.next)
+  symtab_node *node;
+  for (node = symtab_nodes; node; node = node->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;
 }
@@ -957,12 +1204,12 @@ cgraph_first_function_with_gimple_body (void)
 static inline struct cgraph_node *
 cgraph_next_function_with_gimple_body (struct cgraph_node *node)
 {
-  symtab_node node1 = node->symbol.next;
-  for (; node1; node1 = node1->symbol.next)
+  symtab_node *node1 = node->next;
+  for (; node1; node1 = node1->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;
 }
@@ -979,7 +1226,7 @@ tree add_new_static_var (tree type);
 static inline bool
 csi_end_p (cgraph_node_set_iterator csi)
 {
-  return csi.index >= VEC_length (cgraph_node_ptr, csi.set->nodes);
+  return csi.index >= csi.set->nodes.length ();
 }
 
 /* Advance iterator CSI.  */
@@ -993,7 +1240,7 @@ csi_next (cgraph_node_set_iterator *csi)
 static inline struct cgraph_node *
 csi_node (cgraph_node_set_iterator csi)
 {
-  return VEC_index (cgraph_node_ptr, csi.set->nodes, csi.index);
+  return csi.set->nodes[csi.index];
 }
 
 /* Return an iterator to the first node in SET.  */
@@ -1020,14 +1267,14 @@ cgraph_node_in_set_p (struct cgraph_node *node, cgraph_node_set set)
 static inline size_t
 cgraph_node_set_size (cgraph_node_set set)
 {
-  return VEC_length (cgraph_node_ptr, set->nodes);
+  return set->nodes.length ();
 }
 
 /* Return true if iterator VSI points to nothing.  */
 static inline bool
 vsi_end_p (varpool_node_set_iterator vsi)
 {
-  return vsi.index >= VEC_length (varpool_node_ptr, vsi.set->nodes);
+  return vsi.index >= vsi.set->nodes.length ();
 }
 
 /* Advance iterator VSI.  */
@@ -1038,10 +1285,10 @@ vsi_next (varpool_node_set_iterator *vsi)
 }
 
 /* Return the node pointed to by VSI.  */
-static inline struct varpool_node *
+static inline varpool_node *
 vsi_node (varpool_node_set_iterator vsi)
 {
-  return VEC_index (varpool_node_ptr, vsi.set->nodes, vsi.index);
+  return vsi.set->nodes[vsi.index];
 }
 
 /* Return an iterator to the first node in SET.  */
@@ -1057,7 +1304,7 @@ vsi_start (varpool_node_set set)
 
 /* Return true if SET contains NODE.  */
 static inline bool
-varpool_node_in_set_p (struct varpool_node *node, varpool_node_set set)
+varpool_node_in_set_p (varpool_node *node, varpool_node_set set)
 {
   varpool_node_set_iterator vsi;
   vsi = varpool_node_set_find (set, node);
@@ -1068,7 +1315,7 @@ varpool_node_in_set_p (struct varpool_node *node, varpool_node_set set)
 static inline size_t
 varpool_node_set_size (varpool_node_set set)
 {
-  return VEC_length (varpool_node_ptr, set->nodes);
+  return set->nodes.length ();
 }
 
 /* Uniquize all constants that appear in memory.
@@ -1092,14 +1339,14 @@ struct GTY(()) constant_descriptor_tree {
 static inline bool
 cgraph_node_set_nonempty_p (cgraph_node_set set)
 {
-  return !VEC_empty (cgraph_node_ptr, set->nodes);
+  return !set->nodes.is_empty ();
 }
 
 /* Return true if set is nonempty.  */
 static inline bool
 varpool_node_set_nonempty_p (varpool_node_set set)
 {
-  return !VEC_empty (varpool_node_ptr, set->nodes);
+  return !set->nodes.is_empty ();
 }
 
 /* Return true when function NODE is only called directly or it has alias.
@@ -1110,26 +1357,28 @@ static inline bool
 cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
 {
   gcc_assert (!node->global.inlined_to);
-  return (!node->symbol.force_output && !node->symbol.address_taken
-         && !node->symbol.used_from_other_partition
-         && !DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
-         && !DECL_STATIC_DESTRUCTOR (node->symbol.decl)
-         && !node->symbol.externally_visible);
+  return (!node->force_output && !node->address_taken
+         && !node->used_from_other_partition
+         && !DECL_VIRTUAL_P (node->decl)
+         && !DECL_STATIC_CONSTRUCTOR (node->decl)
+         && !DECL_STATIC_DESTRUCTOR (node->decl)
+         && !node->externally_visible);
 }
 
 /* Return true when function NODE can be removed from callgraph
    if all direct calls are eliminated.  */
 
 static inline bool
-varpool_can_remove_if_no_refs (struct varpool_node *node)
+varpool_can_remove_if_no_refs (varpool_node *node)
 {
-  if (DECL_EXTERNAL (node->symbol.decl))
+  if (DECL_EXTERNAL (node->decl))
     return true;
-  return (!node->symbol.force_output && !node->symbol.used_from_other_partition
-         && ((DECL_COMDAT (node->symbol.decl)
-              && !symtab_used_from_object_file_p ((symtab_node) node))
-             || !node->symbol.externally_visible
-             || DECL_HAS_VALUE_EXPR_P (node->symbol.decl)));
+  return (!node->force_output && !node->used_from_other_partition
+         && ((DECL_COMDAT (node->decl)
+              && !node->forced_by_abi
+              && !symtab_used_from_object_file_p (node))
+             || !node->externally_visible
+             || DECL_HAS_VALUE_EXPR_P (node->decl)));
 }
 
 /* Return true when all references to VNODE must be visible in ipa_ref_list.
@@ -1138,12 +1387,12 @@ varpool_can_remove_if_no_refs (struct varpool_node *node)
    The magic uses are all summarized in force_output flag.  */
 
 static inline bool
-varpool_all_refs_explicit_p (struct varpool_node *vnode)
+varpool_all_refs_explicit_p (varpool_node *vnode)
 {
-  return (vnode->analyzed
-         && !vnode->symbol.externally_visible
-         && !vnode->symbol.used_from_other_partition
-         && !vnode->symbol.force_output);
+  return (vnode->definition
+         && !vnode->externally_visible
+         && !vnode->used_from_other_partition
+         && !vnode->force_output);
 }
 
 /* Constant pool accessor function.  */
@@ -1154,60 +1403,25 @@ htab_t constant_pool_htab (void);
 
 /* Return node that alias N is aliasing.  */
 
-static inline struct cgraph_node *
-cgraph_alias_aliased_node (struct cgraph_node *n)
+static inline symtab_node *
+symtab_alias_target (symtab_node *n)
 {
   struct ipa_ref *ref;
-
-  ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
+  ipa_ref_list_reference_iterate (&n->ref_list, 0, ref);
   gcc_checking_assert (ref->use == IPA_REF_ALIAS);
-  if (symtab_function_p (ref->referred))
-    return ipa_ref_node (ref);
-  return NULL;
+  return ref->referred;
 }
 
-/* Return node that alias N is aliasing.  */
-
-static inline struct varpool_node *
-varpool_alias_aliased_node (struct varpool_node *n)
+static inline struct cgraph_node *
+cgraph_alias_target (struct cgraph_node *n)
 {
-  struct ipa_ref *ref;
-
-  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))
-    return ipa_ref_varpool_node (ref);
-  return NULL;
+  return dyn_cast <cgraph_node> (symtab_alias_target (n));
 }
 
-/* Given NODE, walk the alias chain to return the function NODE is alias of.
-   Walk through thunk, too.
-   When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
-
-static inline struct cgraph_node *
-cgraph_function_node (struct cgraph_node *node, enum availability *availability)
+static inline varpool_node *
+varpool_alias_target (varpool_node *n)
 {
-  if (availability)
-    *availability = cgraph_function_body_availability (node);
-  while (node)
-    {
-      if (node->alias && node->analyzed)
-       node = cgraph_alias_aliased_node (node);
-      else if (node->thunk.thunk_p)
-       node = node->callees->callee;
-      else
-       return node;
-      if (node && availability)
-       {
-         enum availability a;
-         a = cgraph_function_body_availability (node);
-         if (a < *availability)
-           *availability = a;
-       }
-    }
-  if (availability)
-    *availability = AVAIL_NOT_AVAILABLE;
-  return NULL;
+  return dyn_cast <varpool_node> (symtab_alias_target (n));
 }
 
 /* Given NODE, walk the alias chain to return the function NODE is alias of.
@@ -1215,55 +1429,36 @@ cgraph_function_node (struct cgraph_node *node, enum availability *availability)
    When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
 
 static inline struct cgraph_node *
-cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *availability)
+cgraph_function_or_thunk_node (struct cgraph_node *node,
+                              enum availability *availability = NULL)
 {
-  if (availability)
-    *availability = cgraph_function_body_availability (node);
-  while (node)
-    {
-      if (node->alias && node->analyzed)
-       node = cgraph_alias_aliased_node (node);
-      else
-       return node;
-      if (node && availability)
-       {
-         enum availability a;
-         a = cgraph_function_body_availability (node);
-         if (a < *availability)
-           *availability = a;
-       }
-    }
-  if (availability)
+  struct cgraph_node *n;
+
+  n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target (node,
+                                                           availability));
+  if (!n && availability)
     *availability = AVAIL_NOT_AVAILABLE;
-  return NULL;
+  return n;
 }
-
 /* Given NODE, walk the alias chain to return the function NODE is alias of.
    Do not walk through thunks.
    When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
 
-static inline struct varpool_node *
-varpool_variable_node (struct varpool_node *node, enum availability *availability)
+static inline varpool_node *
+varpool_variable_node (varpool_node *node,
+                      enum availability *availability = NULL)
 {
-  if (availability)
-    *availability = cgraph_variable_initializer_availability (node);
-  while (node)
-    {
-      if (node->alias && node->analyzed)
-       node = varpool_alias_aliased_node (node);
-      else
-       return node;
-      if (node && availability)
-       {
-         enum availability a;
-         a = cgraph_variable_initializer_availability (node);
-         if (a < *availability)
-           *availability = a;
-       }
-    }
-  if (availability)
+  varpool_node *n;
+
+  if (node)
+    n = dyn_cast <varpool_node> (symtab_alias_ultimate_target (node,
+                                                              availability));
+  else
+    n = NULL;
+
+  if (!n && availability)
     *availability = AVAIL_NOT_AVAILABLE;
-  return NULL;
+  return n;
 }
 
 /* Return true when the edge E represents a direct recursion.  */
@@ -1272,9 +1467,9 @@ cgraph_edge_recursive_p (struct cgraph_edge *e)
 {
   struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL);
   if (e->caller->global.inlined_to)
-    return e->caller->global.inlined_to->symbol.decl == callee->symbol.decl;
+    return e->caller->global.inlined_to->decl == callee->decl;
   else
-    return e->caller->symbol.decl == callee->symbol.decl;
+    return e->caller->decl == callee->decl;
 }
 
 /* Return true if the TM_CLONE bit is set for a given FNDECL.  */
@@ -1293,8 +1488,55 @@ decl_is_tm_clone (const_tree fndecl)
 static inline void
 cgraph_mark_force_output_node (struct cgraph_node *node)
 {
-  node->symbol.force_output = 1;
+  node->force_output = 1;
   gcc_checking_assert (!node->global.inlined_to);
 }
 
+/* Return true when the symbol is real symbol, i.e. it is not inline clone
+   or abstract function kept for debug info purposes only.  */
+
+static inline bool
+symtab_real_symbol_p (symtab_node *node)
+{
+  struct cgraph_node *cnode;
+
+  if (DECL_ABSTRACT (node->decl))
+    return false;
+  if (!is_a <cgraph_node> (node))
+    return true;
+  cnode = cgraph (node);
+  if (cnode->global.inlined_to)
+    return false;
+  return true;
+}
+
+/* Return true if NODE can be discarded by linker from the binary.  */
+
+static inline bool
+symtab_can_be_discarded (symtab_node *node)
+{
+  return (DECL_EXTERNAL (node->decl)
+         || (DECL_ONE_ONLY (node->decl)
+             && node->resolution != LDPR_PREVAILING_DEF
+             && node->resolution != LDPR_PREVAILING_DEF_IRONLY
+             && node->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP));
+}
+
+/* Return true if NODE is local to a particular COMDAT group, and must not
+   be named from outside the COMDAT.  This is used for C++ decloned
+   constructors.  */
+
+static inline bool
+symtab_comdat_local_p (symtab_node *node)
+{
+  return (node->same_comdat_group && !TREE_PUBLIC (node->decl));
+}
+
+/* Return true if ONE and TWO are part of the same COMDAT group.  */
+
+static inline bool
+symtab_in_same_comdat_p (symtab_node *one, symtab_node *two)
+{
+  return DECL_COMDAT_GROUP (one->decl) == DECL_COMDAT_GROUP (two->decl);
+}
 #endif  /* GCC_CGRAPH_H  */