OSDN Git Service

PR c++/46245
[pf3gnuchains/gcc-fork.git] / gcc / cgraph.h
index a9a2962..8be0354 100644 (file)
@@ -1,5 +1,5 @@
 /* Callgraph handling code.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
@@ -21,9 +21,13 @@ along with GCC; see the file COPYING3.  If not see
 
 #ifndef GCC_CGRAPH_H
 #define GCC_CGRAPH_H
+
+#include "plugin-api.h"
+#include "vec.h"
 #include "tree.h"
 #include "basic-block.h"
-#include "ipa-ref.h"
+#include "function.h"
+#include "ipa-ref.h"   /* FIXME: inappropriate dependency of cgraph on IPA.  */
 
 enum availability
 {
@@ -52,23 +56,7 @@ enum availability
 struct lto_file_decl_data;
 
 extern const char * const cgraph_availability_names[];
-
-/* Function inlining information.  */
-
-struct GTY(()) inline_summary
-{
-  /* Estimated stack frame consumption by the function.  */
-  HOST_WIDE_INT estimated_self_stack_size;
-
-  /* Size of the function body.  */
-  int self_size;
-  /* How many instructions are likely going to disappear after inlining.  */
-  int size_inlining_benefit;
-  /* Estimated time spent executing the function body.  */
-  int self_time;
-  /* How much time is going to be saved by inlining.  */
-  int time_inlining_benefit;
-};
+extern const char * const ld_plugin_symbol_resolution_names[];
 
 /* Information about thunk, used only for same body aliases.  */
 
@@ -90,56 +78,32 @@ struct GTY(()) cgraph_local_info {
   /* File stream where this node is being written to.  */
   struct lto_file_decl_data * lto_file_data;
 
-  struct inline_summary inline_summary;
-
   /* Set when function function is visible in current compilation unit only
      and its address is never taken.  */
   unsigned local : 1;
 
   /* Set when function is visible by other units.  */
   unsigned externally_visible : 1;
-
+  
   /* Set once it has been finalized so we consider it to be output.  */
   unsigned finalized : 1;
 
-  /* False when there something makes inlining impossible (such as va_arg).  */
-  unsigned inlinable : 1;
-
-  /* False when there something makes versioning impossible.
-     Currently computed and used only by ipa-cp.  */
-  unsigned versionable : 1;
-
-  /* True when function should be inlined independently on its size.  */
-  unsigned disregard_inline_limits : 1;
+  /* False when function calling convention and signature can not be changed.
+     This is the case when __builtin_apply_args is used.  */
+  unsigned can_change_signature : 1;
 
   /* True when the function has been originally extern inline, but it is
      redefined now.  */
   unsigned redefined_extern_inline : 1;
-
-  /* True if the function is going to be emitted in some other translation
-     unit, referenced from vtable.  */
-  unsigned vtable_method : 1;
 };
 
 /* Information about the function that needs to be computed globally
    once compilation is finished.  Available only with -funit-at-a-time.  */
 
 struct GTY(()) cgraph_global_info {
-  /* Estimated stack frame consumption by the function.  */
-  HOST_WIDE_INT estimated_stack_size;
-  /* Expected offset of the stack frame of inlined function.  */
-  HOST_WIDE_INT stack_frame_offset;
-
   /* For inline clones this points to the function they will be
      inlined into.  */
   struct cgraph_node *inlined_to;
-
-  /* Estimated size of the function after inlining.  */
-  int time;
-  int size;
-
-  /* Estimated growth after inlining.  INT_MIN if not computed.  */
-  int estimated_growth;
 };
 
 /* Information about the function that is propagated by the RTL backend.
@@ -175,20 +139,6 @@ struct GTY(()) cgraph_clone_info
   bitmap combined_args_to_skip;
 };
 
-enum node_frequency {
-  /* This function most likely won't be executed at all.
-     (set only when profile feedback is available or via function attribute). */
-  NODE_FREQUENCY_UNLIKELY_EXECUTED,
-  /* For functions that are known to be executed once (i.e. constructors, destructors
-     and main function.  */
-  NODE_FREQUENCY_EXECUTED_ONCE,
-  /* The default value.  */
-  NODE_FREQUENCY_NORMAL,
-  /* Optimize this function hard
-     (set only when profile feedback is available or via function attribute). */
-  NODE_FREQUENCY_HOT
-};
-
 
 /* The cgraph data structure.
    Each function decl has assigned cgraph_node listing callees and callers.  */
@@ -223,6 +173,8 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
   /* For functions with many calls sites it holds map from call expression
      to the edge to speed up cgraph_edge function.  */
   htab_t GTY((param_is (struct cgraph_edge))) call_site_hash;
+  /* Declaration node used to be clone of. */
+  tree former_clone_of;
 
   PTR GTY ((skip)) aux;
 
@@ -240,14 +192,15 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
 
   /* Expected number of executions: calculated in profile.c.  */
   gcov_type count;
+  /* How to scale counts at materialization time; used to merge
+     LTO units with different number of profile runs.  */
+  int count_materialization_scale;
   /* Unique id of the node.  */
   int uid;
   /* Ordering of all cgraph nodes.  */
   int order;
 
-  /* unique id for profiling. pid is not suitable because of different
-     number of cfg nodes with -fprofile-generate and -fprofile-use */
-  int pid;
+  enum ld_plugin_symbol_resolution resolution;
 
   /* Set when function must be output for some reason.  The primary
      use of this flag is to mark functions needed to be output for
@@ -275,20 +228,24 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
   /* Set once the function has been instantiated and its callee
      lists created.  */
   unsigned analyzed : 1;
-  /* Set when function is available in the other LTRANS partition.  */
+  /* 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 scheduled to be processed by local passes.  */
   unsigned process : 1;
   /* Set for aliases once they got through assemble_alias.  */
   unsigned alias : 1;
-  /* Set for nodes that was constructed and finalized by frontend.  */
-  unsigned finalized_by_frontend : 1;
   /* Set for alias and thunk nodes, same_body points to the node they are alias
      of and they are linked through the next/previous pointers.  */
   unsigned same_body_alias : 1;
   /* How commonly executed the node is.  Initialized during branch
      probabilities pass.  */
   ENUM_BITFIELD (node_frequency) frequency : 2;
+  /* True when function can only be called at startup (from static ctor).  */
+  unsigned only_called_at_startup : 1;
+  /* True when function can only be called at startup (from static dtor).  */
+  unsigned only_called_at_exit : 1;
 };
 
 typedef struct cgraph_node *cgraph_node_ptr;
@@ -299,11 +256,10 @@ DEF_VEC_ALLOC_P(cgraph_node_ptr,gc);
 
 /* A cgraph node set is a collection of cgraph nodes.  A cgraph node
    can appear in multiple sets.  */
-struct GTY(()) cgraph_node_set_def
+struct cgraph_node_set_def
 {
-  htab_t GTY((param_is (struct cgraph_node_set_element_def))) hashtab;
-  VEC(cgraph_node_ptr, gc) *nodes;
-  PTR GTY ((skip)) aux;
+  struct pointer_map_t *map;
+  VEC(cgraph_node_ptr, heap) *nodes;
 };
 
 typedef struct varpool_node *varpool_node_ptr;
@@ -314,11 +270,10 @@ 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 GTY(()) varpool_node_set_def
+struct varpool_node_set_def
 {
-  htab_t GTY((param_is (struct varpool_node_set_element_def))) hashtab;
-  VEC(varpool_node_ptr, gc) *nodes;
-  PTR GTY ((skip)) aux;
+  struct pointer_map_t * map;
+  VEC(varpool_node_ptr, heap) *nodes;
 };
 
 typedef struct cgraph_node_set_def *cgraph_node_set;
@@ -333,17 +288,6 @@ DEF_VEC_P(varpool_node_set);
 DEF_VEC_ALLOC_P(varpool_node_set,gc);
 DEF_VEC_ALLOC_P(varpool_node_set,heap);
 
-/* A cgraph node set element contains an index in the vector of nodes in
-   the set.  */
-struct GTY(()) cgraph_node_set_element_def
-{
-  struct cgraph_node *node;
-  HOST_WIDE_INT index;
-};
-
-typedef struct cgraph_node_set_element_def *cgraph_node_set_element;
-typedef const struct cgraph_node_set_element_def *const_cgraph_node_set_element;
-
 /* Iterator structure for cgraph node sets.  */
 typedef struct
 {
@@ -351,17 +295,6 @@ typedef struct
   unsigned index;
 } cgraph_node_set_iterator;
 
-/* A varpool node set element contains an index in the vector of nodes in
-   the set.  */
-struct GTY(()) varpool_node_set_element_def
-{
-  struct varpool_node *node;
-  HOST_WIDE_INT index;
-};
-
-typedef struct varpool_node_set_element_def *varpool_node_set_element;
-typedef const struct varpool_node_set_element_def *const_varpool_node_set_element;
-
 /* Iterator structure for varpool node sets.  */
 typedef struct
 {
@@ -385,6 +318,9 @@ struct GTY(()) cgraph_indirect_call_info
   HOST_WIDE_INT anc_offset;
   /* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set).  */
   HOST_WIDE_INT otr_token;
+  /* Delta by which must be added to this parameter to compensate for a skipped
+     this adjusting thunk.  */
+  HOST_WIDE_INT thunk_delta;
   /* Type of the object from OBJ_TYPE_REF_OBJECT. */
   tree otr_type;
   /* Index of the parameter that is called.  */
@@ -423,8 +359,6 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgrap
   int frequency;
   /* Unique id of the edge.  */
   int uid;
-  /* Depth of loop nest, 1 means no loop nest.  */
-  unsigned short int loop_nest;
   /* Whether this edge was made direct by indirect inlining.  */
   unsigned int indirect_inlining_edge : 1;
   /* Whether this edge describes an indirect call with an undetermined
@@ -460,9 +394,12 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
   /* Circular list of nodes in the same comdat group if non-NULL.  */
   struct varpool_node *same_comdat_group;
   struct ipa_ref_list ref_list;
+  /* File stream where this node is being written to.  */
+  struct lto_file_decl_data * lto_file_data;
   PTR GTY ((skip)) aux;
   /* Ordering of all cgraph nodes.  */
   int order;
+  enum ld_plugin_symbol_resolution resolution;
 
   /* Set when function must be output - it is externally visible
      or its address is taken.  */
@@ -484,7 +421,9 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
   unsigned alias : 1;
   /* Set when variable is used from other LTRANS partition.  */
   unsigned used_from_other_partition : 1;
-  /* Set when variable is available in the other LTRANS partition.  */
+  /* Set when variable 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;
 };
 
@@ -503,7 +442,6 @@ extern GTY(()) struct cgraph_node *cgraph_nodes;
 extern GTY(()) int cgraph_n_nodes;
 extern GTY(()) int cgraph_max_uid;
 extern GTY(()) int cgraph_edge_max_uid;
-extern GTY(()) int cgraph_max_pid;
 extern bool cgraph_global_info_ready;
 enum cgraph_state
 {
@@ -539,13 +477,17 @@ void cgraph_release_function_body (struct cgraph_node *);
 void cgraph_node_remove_callees (struct cgraph_node *node);
 struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
                                        struct cgraph_node *,
-                                       gimple, gcov_type, int, int);
-struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple, int,
-                                                gcov_type, int, int);
-struct cgraph_node * cgraph_get_node (tree);
-struct cgraph_node *cgraph_node (tree);
-bool cgraph_same_body_alias (tree, tree);
-void cgraph_add_thunk (tree, tree, bool, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree);
+                                       gimple, gcov_type, int);
+struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple,
+                                                int, gcov_type, int);
+struct cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
+struct cgraph_node * cgraph_get_node (const_tree);
+struct cgraph_node * cgraph_get_node_or_alias (const_tree);
+struct cgraph_node * cgraph_create_node (tree);
+struct cgraph_node * cgraph_get_create_node (tree);
+struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree);
+struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, HOST_WIDE_INT,
+                                      HOST_WIDE_INT, tree, tree);
 void cgraph_remove_same_body_alias (struct cgraph_node *);
 struct cgraph_node *cgraph_node_for_asm (tree);
 struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);
@@ -553,7 +495,7 @@ void cgraph_set_call_stmt (struct cgraph_edge *, gimple);
 void cgraph_set_call_stmt_including_clones (struct cgraph_node *, gimple, gimple);
 void cgraph_create_edge_including_clones (struct cgraph_node *,
                                          struct cgraph_node *,
-                                         gimple, gimple, gcov_type, int, int,
+                                         gimple, gimple, gcov_type, int,
                                          cgraph_inline_failed_t);
 void cgraph_update_edges_for_call_stmt (gimple, tree, gimple);
 struct cgraph_local_info *cgraph_local_info (tree);
@@ -562,12 +504,14 @@ struct cgraph_rtl_info *cgraph_rtl_info (tree);
 const char * cgraph_node_name (struct cgraph_node *);
 struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *,
                                        struct cgraph_node *, gimple,
-                                       unsigned, gcov_type, int, int, bool);
-struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type, int,
-                                       int, bool, VEC(cgraph_edge_p,heap) *);
+                                       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);
 
 void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
-void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *);
+void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *,
+                             HOST_WIDE_INT);
 
 struct cgraph_asm_node *cgraph_add_asm_node (tree);
 
@@ -580,23 +524,35 @@ const char* cgraph_inline_failed_string (cgraph_inline_failed_t);
 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,
-                                                 bitmap args_to_skip);
+                                                 bitmap args_to_skip,
+                                                 const char *clone_name);
 
 void cgraph_set_nothrow_flag (struct cgraph_node *, bool);
-void cgraph_set_readonly_flag (struct cgraph_node *, bool);
-void cgraph_set_pure_flag (struct cgraph_node *, bool);
-void cgraph_set_looping_const_or_pure_flag (struct cgraph_node *, bool);
+void cgraph_set_const_flag (struct cgraph_node *, bool, bool);
+void cgraph_set_pure_flag (struct cgraph_node *, bool, bool);
+tree clone_function_name (tree decl, const char *);
+bool cgraph_node_cannot_return (struct cgraph_node *);
+bool cgraph_edge_cannot_lead_to_return (struct cgraph_edge *);
+bool cgraph_will_be_removed_from_program_if_no_direct_calls
+  (struct cgraph_node *node);
+bool cgraph_can_remove_if_no_direct_calls_and_refs_p
+  (struct cgraph_node *node);
+bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution);
+bool cgraph_used_from_object_file_p (struct cgraph_node *node);
+bool varpool_used_from_object_file_p (struct varpool_node *node);
 
 /* In cgraphunit.c  */
+extern FILE *cgraph_dump_file;
 void cgraph_finalize_function (tree, bool);
 void cgraph_mark_if_needed (tree);
+void cgraph_analyze_function (struct cgraph_node *);
 void cgraph_finalize_compilation_unit (void);
 void cgraph_optimize (void);
 void cgraph_mark_needed_node (struct cgraph_node *);
 void cgraph_mark_address_taken_node (struct cgraph_node *);
 void cgraph_mark_reachable_node (struct cgraph_node *);
 bool cgraph_inline_p (struct cgraph_edge *, cgraph_inline_failed_t *reason);
-bool cgraph_preserve_function_body_p (tree);
+bool cgraph_preserve_function_body_p (struct cgraph_node *);
 void verify_cgraph (void);
 void verify_cgraph_node (struct cgraph_node *);
 void cgraph_build_static_cdtor (char which, tree body, int priority);
@@ -605,9 +561,10 @@ void init_cgraph (void);
 struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
                                                VEC(cgraph_edge_p,heap)*,
                                                VEC(ipa_replace_map_p,gc)*,
-                                               bitmap);
-void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, bitmap);
-struct cgraph_node *save_inline_function_body (struct cgraph_node *);
+                                               bitmap, bitmap, basic_block,
+                                               const char *);
+void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, bitmap,
+                              bitmap, basic_block);
 void record_references_in_initializer (tree, bool);
 bool cgraph_process_new_functions (void);
 
@@ -647,7 +604,6 @@ int compute_call_stmt_bb_frequency (tree, basic_block bb);
 
 /* In ipa.c  */
 bool cgraph_remove_unreachable_nodes (bool, FILE *);
-int cgraph_postorder (struct cgraph_node **);
 cgraph_node_set cgraph_node_set_new (void);
 cgraph_node_set_iterator cgraph_node_set_find (cgraph_node_set,
                                               struct cgraph_node *);
@@ -655,6 +611,7 @@ void cgraph_node_set_add (cgraph_node_set, struct cgraph_node *);
 void cgraph_node_set_remove (cgraph_node_set, struct cgraph_node *);
 void dump_cgraph_node_set (FILE *, cgraph_node_set);
 void debug_cgraph_node_set (cgraph_node_set);
+void free_cgraph_node_set (cgraph_node_set);
 
 varpool_node_set varpool_node_set_new (void);
 varpool_node_set_iterator varpool_node_set_find (varpool_node_set,
@@ -663,10 +620,13 @@ void varpool_node_set_add (varpool_node_set, struct varpool_node *);
 void varpool_node_set_remove (varpool_node_set, struct 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 *);
 
 /* 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  */
 extern GTY(()) struct varpool_node *varpool_nodes_queue;
@@ -687,16 +647,18 @@ void cgraph_make_node_local (struct cgraph_node *);
 bool cgraph_node_can_be_local_p (struct cgraph_node *);
 
 
-struct varpool_node * varpool_get_node (tree decl);
+struct varpool_node * varpool_get_node (const_tree decl);
 void varpool_remove_node (struct varpool_node *node);
+void varpool_finalize_named_section_flags (struct varpool_node *node);
 bool varpool_assemble_pending_decls (void);
 bool varpool_assemble_decl (struct varpool_node *node);
 bool varpool_analyze_pending_decls (void);
 void varpool_remove_unreferenced_decls (void);
 void varpool_empty_needed_queue (void);
-bool varpool_extra_name_alias (tree, tree);
+struct varpool_node * varpool_extra_name_alias (tree, tree);
 const char * varpool_node_name (struct varpool_node *node);
 void varpool_reset_queue (void);
+bool const_value_known_p (tree);
 
 /* Walk all reachable static variables.  */
 #define FOR_EACH_STATIC_VARIABLE(node) \
@@ -709,7 +671,7 @@ varpool_first_static_initializer (void)
   struct varpool_node *node;
   for (node = varpool_nodes_queue; node; node = node->next_needed)
     {
-      gcc_assert (TREE_CODE (node->decl) == VAR_DECL);
+      gcc_checking_assert (TREE_CODE (node->decl) == VAR_DECL);
       if (DECL_INITIAL (node->decl))
        return node;
     }
@@ -722,7 +684,7 @@ varpool_next_static_initializer (struct varpool_node *node)
 {
   for (node = node->next_needed; node; node = node->next_needed)
     {
-      gcc_assert (TREE_CODE (node->decl) == VAR_DECL);
+      gcc_checking_assert (TREE_CODE (node->decl) == VAR_DECL);
       if (DECL_INITIAL (node->decl))
        return node;
     }
@@ -734,10 +696,78 @@ varpool_next_static_initializer (struct varpool_node *node)
    for ((node) = varpool_first_static_initializer (); (node); \
         (node) = varpool_next_static_initializer (node))
 
-/* In ipa-inline.c  */
-void cgraph_clone_inlined_nodes (struct cgraph_edge *, bool, bool);
-unsigned int compute_inline_parameters (struct cgraph_node *);
+/* Return first function with body defined.  */
+static inline struct cgraph_node *
+cgraph_first_defined_function (void)
+{
+  struct cgraph_node *node;
+  for (node = cgraph_nodes; node; node = node->next)
+    {
+      if (node->analyzed)
+       return node;
+    }
+  return NULL;
+}
 
+/* Return next reachable static variable with initializer after NODE.  */
+static inline struct cgraph_node *
+cgraph_next_defined_function (struct cgraph_node *node)
+{
+  for (node = node->next; node; node = node->next)
+    {
+      if (node->analyzed)
+       return node;
+    }
+  return NULL;
+}
+
+/* Walk all functions with body defined.  */
+#define FOR_EACH_DEFINED_FUNCTION(node) \
+   for ((node) = cgraph_first_defined_function (); (node); \
+        (node) = cgraph_next_defined_function (node))
+
+
+/* Return true when NODE is a function with Gimple body defined
+   in current unit.  Functions can also be define externally or they
+   can be thunks with no Gimple representation.
+
+   Note that at WPA stage, the function body may not be present in memory.  */
+
+static inline bool
+cgraph_function_with_gimple_body_p (struct cgraph_node *node)
+{
+  return node->analyzed && !node->thunk.thunk_p;
+}
+
+/* Return first function with body defined.  */
+static inline struct cgraph_node *
+cgraph_first_function_with_gimple_body (void)
+{
+  struct cgraph_node *node;
+  for (node = cgraph_nodes; node; node = node->next)
+    {
+      if (cgraph_function_with_gimple_body_p (node))
+       return node;
+    }
+  return NULL;
+}
+
+/* Return next reachable static variable with initializer after NODE.  */
+static inline struct cgraph_node *
+cgraph_next_function_with_gimple_body (struct cgraph_node *node)
+{
+  for (node = node->next; node; node = node->next)
+    {
+      if (cgraph_function_with_gimple_body_p (node))
+       return node;
+    }
+  return NULL;
+}
+
+/* Walk all functions with body defined.  */
+#define FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) \
+   for ((node) = cgraph_first_function_with_gimple_body (); (node); \
+        (node) = cgraph_next_function_with_gimple_body (node))
 
 /* Create a new static variable of type TYPE.  */
 tree add_new_static_var (tree type);
@@ -787,7 +817,7 @@ 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 htab_elements (set->hashtab);
+  return VEC_length (cgraph_node_ptr, set->nodes);
 }
 
 /* Return true if iterator VSI points to nothing.  */
@@ -835,7 +865,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 htab_elements (set->hashtab);
+  return VEC_length (varpool_node_ptr, set->nodes);
 }
 
 /* Uniquize all constants that appear in memory.
@@ -859,14 +889,14 @@ struct GTY(()) constant_descriptor_tree {
 static inline bool
 cgraph_node_set_nonempty_p (cgraph_node_set set)
 {
-  return VEC_length (cgraph_node_ptr, set->nodes);
+  return !VEC_empty (cgraph_node_ptr, set->nodes);
 }
 
 /* Return true if set is nonempty.  */
 static inline bool
 varpool_node_set_nonempty_p (varpool_node_set set)
 {
-  return VEC_length (varpool_node_ptr, set->nodes);
+  return !VEC_empty (varpool_node_ptr, set->nodes);
 }
 
 /* Return true when function NODE is only called directly.
@@ -876,32 +906,42 @@ varpool_node_set_nonempty_p (varpool_node_set set)
 static inline bool
 cgraph_only_called_directly_p (struct cgraph_node *node)
 {
-  return !node->needed && !node->address_taken && !node->local.externally_visible;
+  gcc_assert (!node->global.inlined_to);
+  return (!node->needed && !node->address_taken
+         && !node->reachable_from_other_partition
+         && !DECL_STATIC_CONSTRUCTOR (node->decl)
+         && !DECL_STATIC_DESTRUCTOR (node->decl)
+         && !node->local.externally_visible);
 }
 
 /* Return true when function NODE can be removed from callgraph
    if all direct calls are eliminated.  */
 
 static inline bool
-cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
+cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
 {
-  return (!node->needed && !node->reachable_from_other_partition
-         && (DECL_COMDAT (node->decl) || !node->local.externally_visible));
+  /* Extern inlines can always go, we will use the external definition.  */
+  if (DECL_EXTERNAL (node->decl))
+    return true;
+  return !node->address_taken && cgraph_can_remove_if_no_direct_calls_and_refs_p (node);
 }
 
 /* Return true when function NODE can be removed from callgraph
    if all direct calls are eliminated.  */
 
 static inline bool
-cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
+varpool_can_remove_if_no_refs (struct varpool_node *node)
 {
-  return !node->address_taken && cgraph_can_remove_if_no_direct_calls_and_refs_p (node);
+  return (!node->force_output && !node->used_from_other_partition
+         && (flag_toplevel_reorder || DECL_COMDAT (node->decl)
+             || DECL_ARTIFICIAL (node->decl))
+         && (DECL_COMDAT (node->decl) || !node->externally_visible));
 }
 
 /* Return true when all references to VNODE must be visible in ipa_ref_list.
    i.e. if the variable is not externally visible or not used in some magic
    way (asm statement or such).
-   The magic uses are all sumarized in force_output flag.  */
+   The magic uses are all summarized in force_output flag.  */
 
 static inline bool
 varpool_all_refs_explicit_p (struct varpool_node *vnode)
@@ -914,6 +954,17 @@ varpool_all_refs_explicit_p (struct varpool_node *vnode)
 /* Constant pool accessor function.  */
 htab_t constant_pool_htab (void);
 
+/* Return true when the edge E represents a direct recursion.  */
+static inline bool
+cgraph_edge_recursive_p (struct cgraph_edge *e)
+{
+  if (e->caller->global.inlined_to)
+    return e->caller->global.inlined_to->decl == e->callee->decl;
+  else
+    return e->caller->decl == e->callee->decl;
+}
+
+/* FIXME: inappropriate dependency of cgraph on IPA.  */
 #include "ipa-ref-inline.h"
 
 #endif  /* GCC_CGRAPH_H  */