/* Callgraph handling code.
- Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
Contributed by Jan Hubicka
This file is part of GCC.
#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,
/* 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_BITFIELD (symtab_type) type : 8;
/* The symbols resolution. */
ENUM_BITFIELD (ld_plugin_symbol_resolution) resolution : 8;
- /* Set when function has address taken.
- In current implementation it imply needed flag. */
- unsigned address_taken : 1;
+ /*** 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 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;
- /* Circular list of nodes in the same comdat group if non-NULL. */
- symtab_node same_comdat_group;
+ /* 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;
- /* 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;
-
PTR GTY ((skip)) aux;
};
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;
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;
/* 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. */
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;
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;
};
vec<cgraph_node_ptr> nodes;
};
-typedef struct varpool_node *varpool_node_ptr;
+class varpool_node;
+typedef varpool_node *varpool_node_ptr;
/* A varpool node set is a collection of varpool nodes. A varpool node
/* 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. */
/* 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. */
/* 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 {
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;
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
/* 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. */
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;
- /* To access the following fields,
- use the use dyn_cast or as_a to obtain the concrete type. */
- struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function;
- struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable;
-};
-
/* Report whether or not THIS symtab node is a function, aka cgraph_node. */
template <>
template <>
inline bool
-is_a_helper <cgraph_node>::test (symtab_node_def *p)
+is_a_helper <cgraph_node>::test (symtab_node *p)
{
- return p->symbol.type == SYMTAB_FUNCTION;
+ 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_def *p)
+is_a_helper <varpool_node>::test (symtab_node *p)
{
- return p->symbol.type == SYMTAB_VARIABLE;
+ 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;
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. */
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 *);
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 *,
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);
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);
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);
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 *);
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);
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 decl, bool 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 */
unsigned, gcov_type, int, bool);
struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type,
int, bool, vec<cgraph_edge_p>,
- bool);
+ 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>,
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,
basic_block, const char *);
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 *);
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_for_decl (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 symtab_prevail_in_asm_name_hash (symtab_node *node);
+void varpool_remove_initializer (varpool_node *);
+/* 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. */
}
/* 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)
+ 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)
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
if (varpool_node *vnode1 = dyn_cast <varpool_node> (node1))
return vnode1;
return NULL;
(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)
{
varpool_node *vnode = dyn_cast <varpool_node> (node);
- if (vnode && DECL_INITIAL (node->symbol.decl))
+ 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)
{
varpool_node *vnode1 = dyn_cast <varpool_node> (node1);
- if (vnode1 && DECL_INITIAL (node1->symbol.decl))
+ if (vnode1 && DECL_INITIAL (node1->decl))
return vnode1;
}
return NULL;
(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)
{
varpool_node *vnode = dyn_cast <varpool_node> (node);
- if (vnode && vnode->analyzed)
+ 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)
{
varpool_node *vnode1 = dyn_cast <varpool_node> (node1);
- if (vnode1 && vnode1->analyzed)
+ if (vnode1 && vnode1->definition)
return vnode1;
}
return NULL;
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)
{
cgraph_node *cn = dyn_cast <cgraph_node> (node);
- if (cn && cn->analyzed)
+ if (cn && cn->definition)
return cn;
}
return NULL;
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)
{
cgraph_node *cn1 = dyn_cast <cgraph_node> (node1);
- if (cn1 && cn1->analyzed)
+ if (cn1 && cn1->definition)
return cn1;
}
return NULL;
static inline struct cgraph_node *
cgraph_first_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 (cgraph_node *cn = dyn_cast <cgraph_node> (node))
return cn;
return NULL;
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)
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
if (cgraph_node *cn1 = dyn_cast <cgraph_node> (node1))
return cn1;
return NULL;
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)
{
cgraph_node *cn = dyn_cast <cgraph_node> (node);
if (cn && cgraph_function_with_gimple_body_p (cn))
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)
{
cgraph_node *cn1 = dyn_cast <cgraph_node> (node1);
if (cn1 && cgraph_function_with_gimple_body_p (cn1))
}
/* Return the node pointed to by VSI. */
-static inline struct varpool_node *
+static inline varpool_node *
vsi_node (varpool_node_set_iterator vsi)
{
return vsi.set->nodes[vsi.index];
/* 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);
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_VIRTUAL_P (node->symbol.decl)
- && !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.
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. */
/* 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 (is_a <cgraph_node> (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 (is_a <varpool_node> (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.
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. */
{
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. */
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 extern function kept around just for inlining. */
+ or abstract function kept for debug info purposes only. */
static inline bool
-symtab_real_symbol_p (symtab_node node)
+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;
- if (cnode->abstract_and_needed)
- 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 */