OSDN Git Service

PR c++/51318
[pf3gnuchains/gcc-fork.git] / gcc / cgraph.h
index 51426e6..0efce34 100644 (file)
@@ -1,5 +1,5 @@
 /* Callgraph handling code.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
@@ -21,8 +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 "function.h"
+#include "ipa-ref.h"   /* FIXME: inappropriate dependency of cgraph on IPA.  */
 
 enum availability
 {
@@ -51,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.  */
 
@@ -87,9 +76,7 @@ struct GTY(()) cgraph_thunk_info {
 
 struct GTY(()) cgraph_local_info {
   /* File stream where this node is being written to.  */
-  struct lto_file_decl_data * GTY ((skip)) lto_file_data;
-
-  struct inline_summary inline_summary;
+  struct lto_file_decl_data * lto_file_data;
 
   /* Set when function function is visible in current compilation unit only
      and its address is never taken.  */
@@ -101,47 +88,28 @@ struct GTY(()) cgraph_local_info {
   /* 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 is something makes versioning impossible.  */
+  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 statics_read_for_function and
-     statics_written_for_function contain valid data.  */
-  unsigned for_functions_valid : 1;
-
-  /* True if the function is going to be emitted in some other translation
-     unit, referenced from vtable.  */
-  unsigned vtable_method : 1;
+  /* True if the function may enter serial irrevocable mode.  */
+  unsigned tm_may_enter_irr : 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;
-
-  /* Set iff the function has been inlined at least once.  */
-  bool inlined;
 };
 
 /* Information about the function that is propagated by the RTL backend.
@@ -159,6 +127,8 @@ struct GTY(()) ipa_replace_map
   tree old_tree;
   /* The new (replacing) tree.  */
   tree new_tree;
+  /* Parameter number to replace, when old_tree is NULL.  */
+  int parm_num;
   /* True when a substitution should be done, false otherwise.  */
   bool replace_p;
   /* True when we replace a reference to old_tree.  */
@@ -175,6 +145,7 @@ struct GTY(()) cgraph_clone_info
   bitmap combined_args_to_skip;
 };
 
+
 /* The cgraph data structure.
    Each function decl has assigned cgraph_node listing callees and callers.  */
 
@@ -184,6 +155,9 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
   struct cgraph_edge *callers;
   struct cgraph_node *next;
   struct cgraph_node *previous;
+  /* 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 *origin;
   /* Points to first nested function, if any.  */
@@ -197,12 +171,13 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
   struct cgraph_node *prev_sibling_clone;
   struct cgraph_node *clones;
   struct cgraph_node *clone_of;
-  /* For normal nodes pointer to the list of alias and thunk nodes,
-     in alias/thunk nodes pointer to the normal node.  */
-  struct cgraph_node *same_body;
+  /* Circular list of nodes in the same comdat group if non-NULL.  */
+  struct cgraph_node *same_comdat_group;
   /* 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;
 
@@ -211,6 +186,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
      per-function in order to allow IPA passes to introduce new functions.  */
   VEC(ipa_opt_pass,heap) * GTY((skip)) ipa_transforms_to_apply;
 
+  struct ipa_ref_list ref_list;
   struct cgraph_local_info local;
   struct cgraph_global_info global;
   struct cgraph_rtl_info rtl;
@@ -219,14 +195,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
@@ -247,20 +224,35 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
      cgraph_remove_unreachable_nodes cgraph still can contain unreachable
      nodes when they are needed for virtual clone instantiation.  */
   unsigned reachable : 1;
+  /* Set when function is reachable by call from other LTRANS partition.  */
+  unsigned reachable_from_other_partition : 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 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.  */
+  /* 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;
+  /* 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;
+  /* True when function is the transactional clone of a function which
+     is called only from inside transactions.  */
+  /* ?? We should be able to remove this.  We have enough bits in
+     cgraph to calculate it.  */
+  unsigned tm_clone : 1;
 };
 
 typedef struct cgraph_node *cgraph_node_ptr;
@@ -271,11 +263,24 @@ 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;
+
+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;
 };
 
 typedef struct cgraph_node_set_def *cgraph_node_set;
@@ -284,16 +289,11 @@ DEF_VEC_P(cgraph_node_set);
 DEF_VEC_ALLOC_P(cgraph_node_set,gc);
 DEF_VEC_ALLOC_P(cgraph_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 varpool_node_set_def *varpool_node_set;
 
-typedef struct cgraph_node_set_element_def *cgraph_node_set_element;
-typedef const struct cgraph_node_set_element_def *const_cgraph_node_set_element;
+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
@@ -302,13 +302,41 @@ typedef struct
   unsigned index;
 } cgraph_node_set_iterator;
 
+/* Iterator structure for varpool node sets.  */
+typedef struct
+{
+  varpool_node_set set;
+  unsigned index;
+} varpool_node_set_iterator;
+
 #define DEFCIFCODE(code, string)       CIF_ ## code,
 /* Reasons for inlining failures.  */
-typedef enum {
+typedef enum cgraph_inline_failed_enum {
 #include "cif-code.def"
   CIF_N_REASONS
 } cgraph_inline_failed_t;
 
+/* 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;
+  /* 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;
+  /* Index of the parameter that is called.  */
+  int param_index;
+  /* ECF flags determined from the caller.  */
+  int ecf_flags;
+
+  /* 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;
+};
+
 struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgraph_edge {
   /* Expected number of executions: calculated in profile.c.  */
   gcov_type count;
@@ -319,6 +347,9 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgrap
   struct cgraph_edge *prev_callee;
   struct cgraph_edge *next_callee;
   gimple call_stmt;
+  /* Additional information about an indirect call.  Not cleared when an edge
+     becomes direct.  */
+  struct cgraph_indirect_call_info *indirect_info;
   PTR GTY ((skip (""))) aux;
   /* When equal to CIF_OK, inline this call.  Otherwise, points to the
      explanation why function was not inlined.  */
@@ -332,10 +363,12 @@ 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 describes a call that was originally indirect.  */
-  unsigned int indirect_call : 1;
+  /* 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
+     callee.  */
+  unsigned int indirect_unknown_callee : 1;
+  /* Whether this edge is still a dangling  */
   /* True if the corresponding CALL stmt cannot be inlined.  */
   unsigned int call_stmt_cannot_inline_p : 1;
   /* Can this call throw externally?  */
@@ -353,14 +386,23 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
 /* The varpool data structure.
    Each static variable decl has assigned varpool_node.  */
 
-struct GTY((chain_next ("%h.next"))) varpool_node {
+struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
   tree decl;
+  /* For aliases points to declaration DECL is alias of.  */
+  tree alias_of;
   /* Pointer to the next function in varpool_nodes.  */
-  struct varpool_node *next;
+  struct varpool_node *next, *prev;
   /* Pointer to the next function in varpool_nodes_queue.  */
-  struct varpool_node *next_needed;
+  struct varpool_node *next_needed, *prev_needed;
+  /* 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.  */
@@ -377,8 +419,16 @@ struct GTY((chain_next ("%h.next"))) varpool_node {
   unsigned output : 1;
   /* Set when function is visible by other units.  */
   unsigned externally_visible : 1;
-  /* Set for aliases once they got through assemble_alias.  */
+  /* 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 when variable is used from other LTRANS partition.  */
+  unsigned used_from_other_partition : 1;
+  /* 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;
 };
 
 /* Every top level asm statement is put into a cgraph_asm_node.  */
@@ -396,7 +446,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
 {
@@ -418,6 +467,7 @@ extern GTY(()) struct cgraph_node *cgraph_new_nodes;
 
 extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
 extern GTY(()) int cgraph_order;
+extern bool same_body_aliases_done;
 
 /* In cgraph.c  */
 void dump_cgraph (FILE *);
@@ -427,25 +477,29 @@ void debug_cgraph_node (struct cgraph_node *);
 void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
 void cgraph_remove_edge (struct cgraph_edge *);
 void cgraph_remove_node (struct cgraph_node *);
+void cgraph_add_to_same_comdat_group (struct cgraph_node *, struct cgraph_node *);
 void cgraph_remove_node_and_inline_clones (struct cgraph_node *);
 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_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);
-void cgraph_remove_same_body_alias (struct cgraph_node *);
+                                       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_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);
 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_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);
@@ -454,11 +508,17 @@ 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 *, 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);
+struct cgraph_node *cgraph_create_function_alias (tree, tree);
+void cgraph_call_node_duplication_hooks (struct cgraph_node *node1,
+                                        struct cgraph_node *node2);
 
 void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
+void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *);
+bool cgraph_only_called_directly_p (struct cgraph_node *);
 
 struct cgraph_asm_node *cgraph_add_asm_node (tree);
 
@@ -471,31 +531,62 @@ 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_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 cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node);
+bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution);
+bool cgraph_used_from_object_file_p (struct cgraph_node *);
+bool varpool_used_from_object_file_p (struct varpool_node *);
+bool cgraph_for_node_thunks_and_aliases (struct cgraph_node *,
+                                        bool (*) (struct cgraph_node *, void *),
+                                        void *,
+                                        bool);
+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);
+
 
 /* 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);
 void cgraph_reset_static_var_maps (void);
 void init_cgraph (void);
+struct cgraph_node * cgraph_copy_node_for_versioning (struct cgraph_node *,
+               tree, VEC(cgraph_edge_p,heap)*, bitmap);
 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);
+void cgraph_process_same_body_aliases (void);
 
 bool cgraph_decide_is_function_needed (struct cgraph_node *, tree);
 
@@ -523,15 +614,16 @@ 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 *);
 void cgraph_materialize_all_clones (void);
-
+gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *);
+bool cgraph_propagate_frequency (struct cgraph_node *node);
 /* In cgraphbuild.c  */
 unsigned int rebuild_cgraph_edges (void);
+void cgraph_rebuild_references (void);
 void reset_inline_failed (struct cgraph_node *);
 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 *);
@@ -539,10 +631,23 @@ 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,
+                                              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 *);
+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);
 
 /* 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;
@@ -558,15 +663,28 @@ void dump_varpool_node (FILE *, struct 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 *);
+void cgraph_make_decl_local (tree);
 void cgraph_make_node_local (struct cgraph_node *);
 bool cgraph_node_can_be_local_p (struct cgraph_node *);
 
+
+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);
+struct varpool_node * varpool_extra_name_alias (tree, tree);
+struct varpool_node * varpool_create_variable_alias (tree, tree);
 const char * varpool_node_name (struct varpool_node *node);
+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 *),
+                                  void *, bool);
+void varpool_add_new_variable (tree);
 
 /* Walk all reachable static variables.  */
 #define FOR_EACH_STATIC_VARIABLE(node) \
@@ -579,7 +697,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;
     }
@@ -592,7 +710,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;
     }
@@ -604,30 +722,81 @@ 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;
+}
 
-/* Create a new static variable of type TYPE.  */
-tree add_new_static_var (tree type);
+/* 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.
 
-/* lto-cgraph.c */
+   Note that at WPA stage, the function body may not be present in memory.  */
 
-enum LTO_cgraph_tags
+static inline bool
+cgraph_function_with_gimple_body_p (struct cgraph_node *node)
 {
-  /* Must leave 0 for the stopper.  */
-  LTO_cgraph_avail_node = 1,
-  LTO_cgraph_overwritable_node,
-  LTO_cgraph_unavail_node,
-  LTO_cgraph_edge,
-  LTO_cgraph_last_tag
-};
+  return node->analyzed && !node->thunk.thunk_p && !node->alias;
+}
+
+/* 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;
+}
 
-extern const char * LTO_cgraph_tag_names[LTO_cgraph_last_tag];
+/* 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;
+}
 
-#define LCC_NOT_FOUND  (-1)
+/* 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);
 
 /* Return true if iterator CSI points to nothing.  */
 static inline bool
@@ -674,7 +843,55 @@ 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.  */
+static inline bool
+vsi_end_p (varpool_node_set_iterator vsi)
+{
+  return vsi.index >= VEC_length (varpool_node_ptr, vsi.set->nodes);
+}
+
+/* Advance iterator VSI.  */
+static inline void
+vsi_next (varpool_node_set_iterator *vsi)
+{
+  vsi->index++;
+}
+
+/* Return the node pointed to by VSI.  */
+static inline struct varpool_node *
+vsi_node (varpool_node_set_iterator vsi)
+{
+  return VEC_index (varpool_node_ptr, vsi.set->nodes, vsi.index);
+}
+
+/* Return an iterator to the first node in SET.  */
+static inline varpool_node_set_iterator
+vsi_start (varpool_node_set set)
+{
+  varpool_node_set_iterator vsi;
+
+  vsi.set = set;
+  vsi.index = 0;
+  return vsi;
+}
+
+/* Return true if SET contains NODE.  */
+static inline bool
+varpool_node_in_set_p (struct varpool_node *node, varpool_node_set set)
+{
+  varpool_node_set_iterator vsi;
+  vsi = varpool_node_set_find (set, node);
+  return !vsi_end_p (vsi);
+}
+
+/* Return number of nodes in SET.  */
+static inline size_t
+varpool_node_set_size (varpool_node_set set)
+{
+  return VEC_length (varpool_node_ptr, set->nodes);
 }
 
 /* Uniquize all constants that appear in memory.
@@ -694,27 +911,199 @@ struct GTY(()) constant_descriptor_tree {
   hashval_t hash;
 };
 
-/* Return true when function NODE is only called directly.
+/* Return true if set is nonempty.  */
+static inline bool
+cgraph_node_set_nonempty_p (cgraph_node_set set)
+{
+  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_empty (varpool_node_ptr, set->nodes);
+}
+
+/* Return true when function NODE is only called directly or it has alias.
    i.e. it is not externally visible, address was not taken and
    it is not used in any other non-standard way.  */
 
 static inline bool
-cgraph_only_called_directly_p (struct cgraph_node *node)
+cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node)
 {
-  return !node->needed && !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_p (struct cgraph_node *node)
+varpool_can_remove_if_no_refs (struct varpool_node *node)
 {
-  return (!node->needed
-         && (DECL_COMDAT (node->decl) || !node->local.externally_visible));
+  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 summarized in force_output flag.  */
+
+static inline bool
+varpool_all_refs_explicit_p (struct varpool_node *vnode)
+{
+  return (vnode->analyzed
+         && !vnode->externally_visible
+         && !vnode->used_from_other_partition
+         && !vnode->force_output);
 }
 
 /* Constant pool accessor function.  */
 htab_t constant_pool_htab (void);
 
+/* FIXME: inappropriate dependency of cgraph on IPA.  */
+#include "ipa-ref-inline.h"
+
+/* Return node that alias N is aliasing.  */
+
+static inline struct cgraph_node *
+cgraph_alias_aliased_node (struct cgraph_node *n)
+{
+  struct ipa_ref *ref;
+
+  ipa_ref_list_reference_iterate (&n->ref_list, 0, ref);
+  gcc_checking_assert (ref->use == IPA_REF_ALIAS);
+  if (ref->refered_type == IPA_REF_CGRAPH)
+    return ipa_ref_node (ref);
+  return NULL;
+}
+
+/* Return node that alias N is aliasing.  */
+
+static inline struct varpool_node *
+varpool_alias_aliased_node (struct varpool_node *n)
+{
+  struct ipa_ref *ref;
+
+  ipa_ref_list_reference_iterate (&n->ref_list, 0, ref);
+  gcc_checking_assert (ref->use == IPA_REF_ALIAS);
+  if (ref->refered_type == IPA_REF_VARPOOL)
+    return ipa_ref_varpool_node (ref);
+  return NULL;
+}
+
+/* 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 availablity in the chain.  */
+
+static inline struct cgraph_node *
+cgraph_function_node (struct cgraph_node *node, enum availability *availability)
+{
+  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;
+}
+
+/* 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 availablity in the chain.  */
+
+static inline struct cgraph_node *
+cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *availability)
+{
+  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)
+    *availability = AVAIL_NOT_AVAILABLE;
+  return NULL;
+}
+
+/* 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 availablity in the chain.  */
+
+static inline struct varpool_node *
+varpool_variable_node (struct varpool_node *node, enum availability *availability)
+{
+  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)
+    *availability = AVAIL_NOT_AVAILABLE;
+  return NULL;
+}
+
+/* Return true when the edge E represents a direct recursion.  */
+static inline bool
+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->decl == callee->decl;
+  else
+    return e->caller->decl == callee->decl;
+}
+
+/* Return true if the TM_CLONE bit is set for a given FNDECL.  */
+static inline bool
+decl_is_tm_clone (const_tree fndecl)
+{
+  struct cgraph_node *n = cgraph_get_node (fndecl);
+  if (n)
+    return n->tm_clone;
+  return false;
+}
 #endif  /* GCC_CGRAPH_H  */