cgraph.c revision 169689
157429Smarkm/* Callgraph handling code.
257429Smarkm   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
357429Smarkm   Contributed by Jan Hubicka
457429Smarkm
557429SmarkmThis file is part of GCC.
657429Smarkm
757429SmarkmGCC is free software; you can redistribute it and/or modify it under
860573Skristhe terms of the GNU General Public License as published by the Free
965668SkrisSoftware Foundation; either version 2, or (at your option) any later
1065668Skrisversion.
1165668Skris
1265668SkrisGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1365668SkrisWARRANTY; without even the implied warranty of MERCHANTABILITY or
1465668SkrisFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1560573Skrisfor more details.
1692559Sdes
1765668SkrisYou should have received a copy of the GNU General Public License
1865668Skrisalong with GCC; see the file COPYING.  If not, write to the Free
1965668SkrisSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2065668Skris02110-1301, USA.  */
2165668Skris
2265668Skris/*  This file contains basic routines manipulating call graph and variable pool
2365668Skris
2465668SkrisThe callgraph:
2565668Skris
2665668Skris    The call-graph is data structure designed for intra-procedural optimization
2765668Skris    but it is also used in non-unit-at-a-time compilation to allow easier code
2865668Skris    sharing.
2965668Skris
3065668Skris    The call-graph consist of nodes and edges represented via linked lists.
3165668Skris    Each function (external or not) corresponds to the unique node (in
3265668Skris    contrast to tree DECL nodes where we can have multiple nodes for each
3365668Skris    function).
3465668Skris
3565668Skris    The mapping from declarations to call-graph nodes is done using hash table
3665668Skris    based on DECL_ASSEMBLER_NAME, so it is essential for assembler name to
3765668Skris    not change once the declaration is inserted into the call-graph.
3865668Skris    The call-graph nodes are created lazily using cgraph_node function when
3957429Smarkm    called for unknown declaration.
4057429Smarkm
4157429Smarkm    When built, there is one edge for each direct call.  It is possible that
4292559Sdes    the reference will be later optimized out.  The call-graph is built
4374500Sgreen    conservatively in order to make conservative data flow analysis possible.
4457429Smarkm
4557429Smarkm    The callgraph at the moment does not represent indirect calls or calls
4676262Sgreen    from other compilation unit.  Flag NEEDED is set for each node that may
4776262Sgreen    be accessed in such an invisible way and it shall be considered an
4857429Smarkm    entry point to the callgraph.
4957429Smarkm
5057429Smarkm    Interprocedural information:
5176262Sgreen
5276262Sgreen      Callgraph is place to store data needed for interprocedural optimization.
5357429Smarkm      All data structures are divided into three components: local_info that
5457429Smarkm      is produced while analyzing the function, global_info that is result
5576262Sgreen      of global walking of the callgraph on the end of compilation and
5665668Skris      rtl_info used by RTL backend to propagate data from already compiled
5765668Skris      functions to their callers.
5892559Sdes
5965668Skris    Inlining plans:
6057429Smarkm
6192559Sdes      The function inlining information is decided in advance and maintained
6257429Smarkm      in the callgraph as so called inline plan.
6357429Smarkm      For each inlined call, the callee's node is cloned to represent the
6457429Smarkm      new function copy produced by inliner.
6557429Smarkm      Each inlined call gets a unique corresponding clone node of the callee
6657429Smarkm      and the data structure is updated while inlining is performed, so
6792559Sdes      the clones are eliminated and their callee edges redirected to the
6857429Smarkm      caller.
6957429Smarkm
7057429Smarkm      Each edge has "inline_failed" field.  When the field is set to NULL,
7192559Sdes      the call will be inlined.  When it is non-NULL it contains a reason
7257429Smarkm      why inlining wasn't performed.
7357429Smarkm
7457429Smarkm
7557429SmarkmThe varpool data structure:
7657429Smarkm
7792559Sdes    Varpool is used to maintain variables in similar manner as call-graph
7857429Smarkm    is used for functions.  Most of the API is symmetric replacing cgraph
7976262Sgreen    function prefix by cgraph_varpool  */
8057429Smarkm
8157429Smarkm
8292559Sdes#include "config.h"
8357429Smarkm#include "system.h"
8457429Smarkm#include "coretypes.h"
8557429Smarkm#include "tm.h"
8657429Smarkm#include "tree.h"
8757429Smarkm#include "tree-inline.h"
8857429Smarkm#include "langhooks.h"
8957429Smarkm#include "hashtab.h"
9057429Smarkm#include "toplev.h"
9160573Skris#include "flags.h"
9260573Skris#include "ggc.h"
9360573Skris#include "debug.h"
9457429Smarkm#include "target.h"
9557429Smarkm#include "basic-block.h"
9657429Smarkm#include "cgraph.h"
9757429Smarkm#include "varray.h"
9892559Sdes#include "output.h"
9957429Smarkm#include "intl.h"
10057429Smarkm#include "tree-gimple.h"
10157429Smarkm#include "tree-dump.h"
10257429Smarkm
10357429Smarkmstatic void cgraph_node_remove_callers (struct cgraph_node *node);
10457429Smarkmstatic inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
10557429Smarkmstatic inline void cgraph_edge_remove_callee (struct cgraph_edge *e);
10657429Smarkm
10757429Smarkm/* Hash table used to convert declarations into nodes.  */
10857429Smarkmstatic GTY((param_is (struct cgraph_node))) htab_t cgraph_hash;
10992559Sdes
11092559Sdes/* The linked list of cgraph nodes.  */
11192559Sdesstruct cgraph_node *cgraph_nodes;
11292559Sdes
11392559Sdes/* Queue of cgraph nodes scheduled to be lowered.  */
11492559Sdesstruct cgraph_node *cgraph_nodes_queue;
11592559Sdes
11692559Sdes/* Queue of cgraph nodes scheduled to be expanded.  This is a
11792559Sdes   secondary queue used during optimization to accommodate passes that
11892559Sdes   may generate new functions that need to be optimized and expanded.  */
11992559Sdesstruct cgraph_node *cgraph_expand_queue;
12092559Sdes
12192559Sdes/* Number of nodes in existence.  */
12292559Sdesint cgraph_n_nodes;
12392559Sdes
12492559Sdes/* Maximal uid used in cgraph nodes.  */
12592559Sdesint cgraph_max_uid;
12692559Sdes
12792559Sdes/* Set when whole unit has been analyzed so we can access global info.  */
12892559Sdesbool cgraph_global_info_ready = false;
12992559Sdes
13092559Sdes/* Set when the cgraph is fully build and the basic flags are computed.  */
13192559Sdesbool cgraph_function_flags_ready = false;
13292559Sdes
13392559Sdes/* Hash table used to convert declarations into nodes.  */
13492559Sdesstatic GTY((param_is (struct cgraph_varpool_node))) htab_t cgraph_varpool_hash;
13592559Sdes
13692559Sdes/* Queue of cgraph nodes scheduled to be lowered and output.  */
13776262Sgreenstruct cgraph_varpool_node *cgraph_varpool_nodes_queue, *cgraph_varpool_first_unanalyzed_node;
13889703Sru
13976262Sgreen/* The linked list of cgraph varpool nodes.  */
14092559Sdesstruct cgraph_varpool_node *cgraph_varpool_nodes;
14192559Sdes
14276262Sgreen/* End of the varpool queue.  */
14392559Sdesstruct cgraph_varpool_node *cgraph_varpool_last_needed_node;
14457429Smarkm
14560573Skris/* Linked list of cgraph asm nodes.  */
14660573Skrisstruct cgraph_asm_node *cgraph_asm_nodes;
14760573Skris
14860573Skris/* Last node in cgraph_asm_nodes.  */
14992559Sdesstatic GTY(()) struct cgraph_asm_node *cgraph_asm_last_node;
15091688Snectar
15160573Skris/* The order index of the next cgraph node to be created.  This is
15260573Skris   used so that we can sort the cgraph nodes in order by when we saw
15360573Skris   them, to support -fno-toplevel-reorder.  */
15492559Sdesint cgraph_order;
15592559Sdes
15660573Skrisstatic hashval_t hash_node (const void *);
15760573Skrisstatic int eq_node (const void *, const void *);
15860573Skris
15960573Skris/* Returns a hash code for P.  */
16060573Skris
16160573Skrisstatic hashval_t
16257429Smarkmhash_node (const void *p)
16360573Skris{
16460573Skris  const struct cgraph_node *n = (const struct cgraph_node *) p;
16560573Skris  return (hashval_t) DECL_UID (n->decl);
16660573Skris}
16792559Sdes
16869587Sgreen/* Returns nonzero if P1 and P2 are equal.  */
16969587Sgreen
17060573Skrisstatic int
17160573Skriseq_node (const void *p1, const void *p2)
17276262Sgreen{
17376262Sgreen  const struct cgraph_node *n1 = (const struct cgraph_node *) p1;
17476262Sgreen  const struct cgraph_node *n2 = (const struct cgraph_node *) p2;
17576262Sgreen  return DECL_UID (n1->decl) == DECL_UID (n2->decl);
17660573Skris}
17760573Skris
17860573Skris/* Allocate new callgraph node and insert it into basic data structures.  */
17960573Skrisstatic struct cgraph_node *
18060573Skriscgraph_create_node (void)
18160573Skris{
18260573Skris  struct cgraph_node *node;
18369587Sgreen
18474500Sgreen  node = GGC_CNEW (struct cgraph_node);
18574500Sgreen  node->next = cgraph_nodes;
18676262Sgreen  node->uid = cgraph_max_uid++;
18774500Sgreen  node->order = cgraph_order++;
18874500Sgreen  if (cgraph_nodes)
18976262Sgreen    cgraph_nodes->previous = node;
19074500Sgreen  node->previous = NULL;
19174500Sgreen  node->global.estimated_growth = INT_MIN;
19274500Sgreen  cgraph_nodes = node;
19374500Sgreen  cgraph_n_nodes++;
19474500Sgreen  return node;
19574500Sgreen}
19669587Sgreen
19769587Sgreen/* Return cgraph node assigned to DECL.  Create new one when needed.  */
19869587Sgreenstruct cgraph_node *
19969587Sgreencgraph_node (tree decl)
20069587Sgreen{
20169587Sgreen  struct cgraph_node key, *node, **slot;
20269587Sgreen
20369587Sgreen  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
20469587Sgreen
20560573Skris  if (!cgraph_hash)
20660573Skris    cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
20760573Skris
20857429Smarkm  key.decl = decl;
20957429Smarkm
21057429Smarkm  slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT);
21157429Smarkm
21292559Sdes  if (*slot)
21360573Skris    {
21469587Sgreen      node = *slot;
21557429Smarkm      if (!node->master_clone)
21657429Smarkm	node->master_clone = node;
21757429Smarkm      return node;
21857429Smarkm    }
21957429Smarkm
22057429Smarkm  node = cgraph_create_node ();
22157429Smarkm  node->decl = decl;
22292559Sdes  *slot = node;
22357429Smarkm  if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
22492559Sdes    {
22592559Sdes      node->origin = cgraph_node (DECL_CONTEXT (decl));
22657429Smarkm      node->next_nested = node->origin->nested;
22757429Smarkm      node->origin->nested = node;
22857429Smarkm      node->master_clone = node;
22992559Sdes    }
23057429Smarkm  return node;
23157429Smarkm}
23257429Smarkm
23357429Smarkm/* Insert already constructed node into hashtable.  */
23457429Smarkm
23557429Smarkmvoid
23657429Smarkmcgraph_insert_node_to_hashtable (struct cgraph_node *node)
23757429Smarkm{
23869587Sgreen  struct cgraph_node **slot;
23992559Sdes
24057429Smarkm  slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, node, INSERT);
24192559Sdes
24257429Smarkm  gcc_assert (!*slot);
24392559Sdes  *slot = node;
24492559Sdes}
24592559Sdes
24657429Smarkm/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL.  */
24757429Smarkm
24860573Skrisstatic bool
24992559Sdesdecl_assembler_name_equal (tree decl, tree asmname)
25092559Sdes{
25192559Sdes  tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
25269587Sgreen
25357429Smarkm  if (decl_asmname == asmname)
25457429Smarkm    return true;
25560573Skris
25660573Skris  /* If the target assembler name was set by the user, things are trickier.
25760573Skris     We have a leading '*' to begin with.  After that, it's arguable what
25860573Skris     is the correct thing to do with -fleading-underscore.  Arguably, we've
25960573Skris     historically been doing the wrong thing in assemble_alias by always
26057429Smarkm     printing the leading underscore.  Since we're not changing that, make
26157429Smarkm     sure user_label_prefix follows the '*' before matching.  */
26260573Skris  if (IDENTIFIER_POINTER (decl_asmname)[0] == '*')
26360573Skris    {
26492559Sdes      const char *decl_str = IDENTIFIER_POINTER (decl_asmname) + 1;
26592559Sdes      size_t ulp_len = strlen (user_label_prefix);
26692559Sdes
26792559Sdes      if (ulp_len == 0)
26865668Skris	;
26957429Smarkm      else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
27092559Sdes	decl_str += ulp_len;
27157429Smarkm      else
27292559Sdes	return false;
27392559Sdes
27492559Sdes      return strcmp (decl_str, IDENTIFIER_POINTER (asmname)) == 0;
27592559Sdes    }
27692559Sdes
27792559Sdes  return false;
27892559Sdes}
27992559Sdes
28092559Sdes
28192559Sdes/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
28292559Sdes   Return NULL if there's no such node.  */
28392559Sdes
28492559Sdesstruct cgraph_node *
28592559Sdescgraph_node_for_asm (tree asmname)
28692559Sdes{
28792559Sdes  struct cgraph_node *node;
28892559Sdes
28992559Sdes  for (node = cgraph_nodes; node ; node = node->next)
29060573Skris    if (decl_assembler_name_equal (node->decl, asmname))
29192559Sdes      return node;
29260573Skris
29392559Sdes  return NULL;
29492559Sdes}
29592559Sdes
29692559Sdes/* Returns a hash value for X (which really is a die_struct).  */
29792559Sdes
29892559Sdesstatic hashval_t
29992559Sdesedge_hash (const void *x)
30092559Sdes{
30192559Sdes  return htab_hash_pointer (((struct cgraph_edge *) x)->call_stmt);
30260573Skris}
30357429Smarkm
30460573Skris/* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y.  */
30560573Skris
30692559Sdesstatic int
30760573Skrisedge_eq (const void *x, const void *y)
30857429Smarkm{
30992559Sdes  return ((struct cgraph_edge *) x)->call_stmt == y;
31092559Sdes}
31192559Sdes
31292559Sdes/* Return callgraph edge representing CALL_EXPR statement.  */
31392559Sdesstruct cgraph_edge *
31492559Sdescgraph_edge (struct cgraph_node *node, tree call_stmt)
31592559Sdes{
31660573Skris  struct cgraph_edge *e, *e2;
31757429Smarkm  int n = 0;
31860573Skris
31960573Skris  if (node->call_site_hash)
32060573Skris    return htab_find_with_hash (node->call_site_hash, call_stmt,
32192559Sdes      				htab_hash_pointer (call_stmt));
32260573Skris
32392559Sdes  /* This loop may turn out to be performance problem.  In such case adding
32492559Sdes     hashtables into call nodes with very many edges is probably best
32576262Sgreen     solution.  It is not good idea to add pointer into CALL_EXPR itself
32692559Sdes     because we want to make possible having multiple cgraph nodes representing
32792559Sdes     different clones of the same body before the body is actually cloned.  */
32892559Sdes  for (e = node->callees; e; e= e->next_callee)
32992559Sdes    {
33092559Sdes      if (e->call_stmt == call_stmt)
33192559Sdes	break;
33292559Sdes      n++;
33392559Sdes    }
33476262Sgreen  if (n > 100)
33576262Sgreen    {
33660573Skris      node->call_site_hash = htab_create_ggc (120, edge_hash, edge_eq, NULL);
33760573Skris      for (e2 = node->callees; e2; e2 = e2->next_callee)
33860573Skris	{
33960573Skris          void **slot;
34060573Skris	  slot = htab_find_slot_with_hash (node->call_site_hash,
34160573Skris					   e2->call_stmt,
34260573Skris					   htab_hash_pointer (e2->call_stmt),
34360573Skris					   INSERT);
34460573Skris	  gcc_assert (!*slot);
34560573Skris	  *slot = e2;
34692559Sdes	}
34792559Sdes    }
34857429Smarkm  return e;
34957429Smarkm}
35092559Sdes
35192559Sdes/* Change call_smtt of edge E to NEW_STMT.  */
35292559Sdesvoid
35392559Sdescgraph_set_call_stmt (struct cgraph_edge *e, tree new_stmt)
35492559Sdes{
35592559Sdes  if (e->caller->call_site_hash)
35692559Sdes    {
35792559Sdes      htab_remove_elt_with_hash (e->caller->call_site_hash,
35892559Sdes				 e->call_stmt,
35992559Sdes				 htab_hash_pointer (e->call_stmt));
36057429Smarkm    }
36192559Sdes  e->call_stmt = new_stmt;
36292559Sdes  if (e->caller->call_site_hash)
36392559Sdes    {
36492559Sdes      void **slot;
36592559Sdes      slot = htab_find_slot_with_hash (e->caller->call_site_hash,
36692559Sdes				       e->call_stmt,
36792559Sdes				       htab_hash_pointer
36892559Sdes				       (e->call_stmt), INSERT);
36992559Sdes      gcc_assert (!*slot);
37092559Sdes      *slot = e;
37192559Sdes    }
37292559Sdes}
37392559Sdes
37492559Sdes/* Create edge from CALLER to CALLEE in the cgraph.  */
37592559Sdes
37692559Sdesstruct cgraph_edge *
37792559Sdescgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
37892559Sdes		    tree call_stmt, gcov_type count, int nest)
37992559Sdes{
38092559Sdes  struct cgraph_edge *edge = GGC_NEW (struct cgraph_edge);
38192559Sdes#ifdef ENABLE_CHECKING
38292559Sdes  struct cgraph_edge *e;
38392559Sdes
38492559Sdes  for (e = caller->callees; e; e = e->next_callee)
38592559Sdes    gcc_assert (e->call_stmt != call_stmt);
38692559Sdes#endif
38792559Sdes
38892559Sdes  gcc_assert (get_call_expr_in (call_stmt));
38992559Sdes
39092559Sdes  if (!DECL_SAVED_TREE (callee->decl))
39192559Sdes    edge->inline_failed = N_("function body not available");
39292559Sdes  else if (callee->local.redefined_extern_inline)
39392559Sdes    edge->inline_failed = N_("redefined extern inline functions are not "
39492559Sdes			     "considered for inlining");
39592559Sdes  else if (callee->local.inlinable)
39692559Sdes    edge->inline_failed = N_("function not considered for inlining");
39792559Sdes  else
39892559Sdes    edge->inline_failed = N_("function not inlinable");
39992559Sdes
40092559Sdes  edge->aux = NULL;
40192559Sdes
40292559Sdes  edge->caller = caller;
40392559Sdes  edge->callee = callee;
40492559Sdes  edge->call_stmt = call_stmt;
40592559Sdes  edge->prev_caller = NULL;
40692559Sdes  edge->next_caller = callee->callers;
40792559Sdes  if (callee->callers)
40892559Sdes    callee->callers->prev_caller = edge;
40992559Sdes  edge->prev_callee = NULL;
41092559Sdes  edge->next_callee = caller->callees;
41192559Sdes  if (caller->callees)
41292559Sdes    caller->callees->prev_callee = edge;
41392559Sdes  caller->callees = edge;
41492559Sdes  callee->callers = edge;
41592559Sdes  edge->count = count;
41692559Sdes  edge->loop_nest = nest;
41792559Sdes  if (caller->call_site_hash)
41892559Sdes    {
41992559Sdes      void **slot;
42092559Sdes      slot = htab_find_slot_with_hash (caller->call_site_hash,
42192559Sdes				       edge->call_stmt,
42292559Sdes				       htab_hash_pointer
42392559Sdes					 (edge->call_stmt),
42492559Sdes				       INSERT);
42592559Sdes      gcc_assert (!*slot);
42692559Sdes      *slot = edge;
42792559Sdes    }
42892559Sdes  return edge;
42992559Sdes}
43092559Sdes
43192559Sdes/* Remove the edge E from the list of the callers of the callee.  */
43292559Sdes
43392559Sdesstatic inline void
43492559Sdescgraph_edge_remove_callee (struct cgraph_edge *e)
43592559Sdes{
43692559Sdes  if (e->prev_caller)
43792559Sdes    e->prev_caller->next_caller = e->next_caller;
43892559Sdes  if (e->next_caller)
43992559Sdes    e->next_caller->prev_caller = e->prev_caller;
44092559Sdes  if (!e->prev_caller)
44192559Sdes    e->callee->callers = e->next_caller;
44292559Sdes}
44392559Sdes
44492559Sdes/* Remove the edge E from the list of the callees of the caller.  */
44592559Sdes
44692559Sdesstatic inline void
44792559Sdescgraph_edge_remove_caller (struct cgraph_edge *e)
44892559Sdes{
44992559Sdes  if (e->prev_callee)
45092559Sdes    e->prev_callee->next_callee = e->next_callee;
45192559Sdes  if (e->next_callee)
45292559Sdes    e->next_callee->prev_callee = e->prev_callee;
45392559Sdes  if (!e->prev_callee)
45492559Sdes    e->caller->callees = e->next_callee;
45592559Sdes  if (e->caller->call_site_hash)
45692559Sdes    htab_remove_elt_with_hash (e->caller->call_site_hash,
45792559Sdes			       e->call_stmt,
45892559Sdes	  		       htab_hash_pointer (e->call_stmt));
45992559Sdes}
46092559Sdes
46192559Sdes/* Remove the edge E in the cgraph.  */
46292559Sdes
46392559Sdesvoid
46492559Sdescgraph_remove_edge (struct cgraph_edge *e)
46592559Sdes{
46692559Sdes  /* Remove from callers list of the callee.  */
46792559Sdes  cgraph_edge_remove_callee (e);
46892559Sdes
46992559Sdes  /* Remove from callees list of the callers.  */
47092559Sdes  cgraph_edge_remove_caller (e);
47192559Sdes}
47292559Sdes
47392559Sdes/* Redirect callee of E to N.  The function does not update underlying
47492559Sdes   call expression.  */
47592559Sdes
47692559Sdesvoid
47792559Sdescgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n)
47892559Sdes{
47992559Sdes  /* Remove from callers list of the current callee.  */
48092559Sdes  cgraph_edge_remove_callee (e);
48192559Sdes
48292559Sdes  /* Insert to callers list of the new callee.  */
48392559Sdes  e->prev_caller = NULL;
48492559Sdes  if (n->callers)
48592559Sdes    n->callers->prev_caller = e;
48692559Sdes  e->next_caller = n->callers;
48792559Sdes  n->callers = e;
48892559Sdes  e->callee = n;
48992559Sdes}
49092559Sdes
49192559Sdes/* Remove all callees from the node.  */
49292559Sdes
49392559Sdesvoid
49492559Sdescgraph_node_remove_callees (struct cgraph_node *node)
49592559Sdes{
49692559Sdes  struct cgraph_edge *e;
49792559Sdes
49892559Sdes  /* It is sufficient to remove the edges from the lists of callers of
49992559Sdes     the callees.  The callee list of the node can be zapped with one
50092559Sdes     assignment.  */
50192559Sdes  for (e = node->callees; e; e = e->next_callee)
50292559Sdes    cgraph_edge_remove_callee (e);
50392559Sdes  node->callees = NULL;
50492559Sdes  if (node->call_site_hash)
50592559Sdes    {
50692559Sdes      htab_delete (node->call_site_hash);
50792559Sdes      node->call_site_hash = NULL;
50892559Sdes    }
50992559Sdes}
51092559Sdes
51192559Sdes/* Remove all callers from the node.  */
51292559Sdes
51392559Sdesstatic void
51492559Sdescgraph_node_remove_callers (struct cgraph_node *node)
51592559Sdes{
51692559Sdes  struct cgraph_edge *e;
51792559Sdes
51892559Sdes  /* It is sufficient to remove the edges from the lists of callees of
51992559Sdes     the callers.  The caller list of the node can be zapped with one
52092559Sdes     assignment.  */
52192559Sdes  for (e = node->callers; e; e = e->next_caller)
52292559Sdes    cgraph_edge_remove_caller (e);
52392559Sdes  node->callers = NULL;
52492559Sdes}
52592559Sdes
52692559Sdes/* Remove the node from cgraph.  */
52792559Sdes
52892559Sdesvoid
52992559Sdescgraph_remove_node (struct cgraph_node *node)
53092559Sdes{
53192559Sdes  void **slot;
53292559Sdes  bool kill_body = false;
53392559Sdes
53492559Sdes  cgraph_node_remove_callers (node);
53592559Sdes  cgraph_node_remove_callees (node);
53692559Sdes  /* Incremental inlining access removed nodes stored in the postorder list.
53792559Sdes     */
53892559Sdes  node->needed = node->reachable = false;
53992559Sdes  while (node->nested)
54092559Sdes    cgraph_remove_node (node->nested);
54192559Sdes  if (node->origin)
54292559Sdes    {
54392559Sdes      struct cgraph_node **node2 = &node->origin->nested;
54492559Sdes
54592559Sdes      while (*node2 != node)
54692559Sdes	node2 = &(*node2)->next_nested;
54792559Sdes      *node2 = node->next_nested;
54892559Sdes    }
54992559Sdes  if (node->previous)
55092559Sdes    node->previous->next = node->next;
55192559Sdes  else
55292559Sdes    cgraph_nodes = node->next;
55392559Sdes  if (node->next)
55492559Sdes    node->next->previous = node->previous;
55592559Sdes  node->next = NULL;
55692559Sdes  node->previous = NULL;
55792559Sdes  slot = htab_find_slot (cgraph_hash, node, NO_INSERT);
55892559Sdes  if (*slot == node)
55992559Sdes    {
56092559Sdes      if (node->next_clone)
56192559Sdes      {
56292559Sdes	struct cgraph_node *new_node = node->next_clone;
56392559Sdes	struct cgraph_node *n;
56492559Sdes
56592559Sdes	/* Make the next clone be the master clone */
56692559Sdes	for (n = new_node; n; n = n->next_clone)
56792559Sdes	  n->master_clone = new_node;
56892559Sdes
56992559Sdes	*slot = new_node;
57092559Sdes	node->next_clone->prev_clone = NULL;
57192559Sdes      }
57292559Sdes      else
57392559Sdes	{
57492559Sdes	  htab_clear_slot (cgraph_hash, slot);
57592559Sdes	  kill_body = true;
57692559Sdes	}
57792559Sdes    }
57892559Sdes  else
57992559Sdes    {
58092559Sdes      node->prev_clone->next_clone = node->next_clone;
58192559Sdes      if (node->next_clone)
58292559Sdes	node->next_clone->prev_clone = node->prev_clone;
58392559Sdes    }
58492559Sdes
58592559Sdes  /* While all the clones are removed after being proceeded, the function
58692559Sdes     itself is kept in the cgraph even after it is compiled.  Check whether
58792559Sdes     we are done with this body and reclaim it proactively if this is the case.
58892559Sdes     */
58992559Sdes  if (!kill_body && *slot)
59092559Sdes    {
59192559Sdes      struct cgraph_node *n = (struct cgraph_node *) *slot;
59292559Sdes      if (!n->next_clone && !n->global.inlined_to
59392559Sdes	  && (cgraph_global_info_ready
59492559Sdes	      && (TREE_ASM_WRITTEN (n->decl) || DECL_EXTERNAL (n->decl))))
59592559Sdes	kill_body = true;
59692559Sdes    }
59792559Sdes
59892559Sdes  if (kill_body && flag_unit_at_a_time)
59992559Sdes    {
60092559Sdes      DECL_SAVED_TREE (node->decl) = NULL;
60192559Sdes      DECL_STRUCT_FUNCTION (node->decl) = NULL;
60292559Sdes      DECL_INITIAL (node->decl) = error_mark_node;
60392559Sdes    }
60492559Sdes  node->decl = NULL;
60592559Sdes  if (node->call_site_hash)
60692559Sdes    {
60792559Sdes      htab_delete (node->call_site_hash);
60892559Sdes      node->call_site_hash = NULL;
60992559Sdes    }
61092559Sdes  cgraph_n_nodes--;
61192559Sdes  /* Do not free the structure itself so the walk over chain can continue.  */
61292559Sdes}
61392559Sdes
61492559Sdes/* Notify finalize_compilation_unit that given node is reachable.  */
61592559Sdes
61692559Sdesvoid
61792559Sdescgraph_mark_reachable_node (struct cgraph_node *node)
61892559Sdes{
61992559Sdes  if (!node->reachable && node->local.finalized)
62092559Sdes    {
62192559Sdes      notice_global_symbol (node->decl);
62292559Sdes      node->reachable = 1;
62392559Sdes      gcc_assert (!cgraph_global_info_ready);
62492559Sdes
62592559Sdes      node->next_needed = cgraph_nodes_queue;
62692559Sdes      cgraph_nodes_queue = node;
62792559Sdes    }
62892559Sdes}
62992559Sdes
63092559Sdes/* Likewise indicate that a node is needed, i.e. reachable via some
63192559Sdes   external means.  */
63292559Sdes
63392559Sdesvoid
63492559Sdescgraph_mark_needed_node (struct cgraph_node *node)
63592559Sdes{
63692559Sdes  node->needed = 1;
63792559Sdes  cgraph_mark_reachable_node (node);
63892559Sdes}
63992559Sdes
64092559Sdes/* Return local info for the compiled function.  */
64192559Sdes
64292559Sdesstruct cgraph_local_info *
64392559Sdescgraph_local_info (tree decl)
64492559Sdes{
64592559Sdes  struct cgraph_node *node;
64692559Sdes
64792559Sdes  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
64892559Sdes  node = cgraph_node (decl);
64992559Sdes  return &node->local;
65092559Sdes}
65192559Sdes
65292559Sdes/* Return local info for the compiled function.  */
65392559Sdes
65492559Sdesstruct cgraph_global_info *
65592559Sdescgraph_global_info (tree decl)
65692559Sdes{
65792559Sdes  struct cgraph_node *node;
65892559Sdes
65992559Sdes  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL && cgraph_global_info_ready);
66092559Sdes  node = cgraph_node (decl);
66192559Sdes  return &node->global;
66292559Sdes}
66360573Skris
66460573Skris/* Return local info for the compiled function.  */
66557429Smarkm
66660573Skrisstruct cgraph_rtl_info *
66760573Skriscgraph_rtl_info (tree decl)
66860573Skris{
66960573Skris  struct cgraph_node *node;
67060573Skris
67160573Skris  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
67260573Skris  node = cgraph_node (decl);
67357429Smarkm  if (decl != current_function_decl
67492559Sdes      && !TREE_ASM_WRITTEN (node->decl))
67560573Skris    return NULL;
67657429Smarkm  return &node->rtl;
67760573Skris}
67860573Skris
67960573Skris/* Return name of the node used in debug output.  */
68092559Sdesconst char *
68176262Sgreencgraph_node_name (struct cgraph_node *node)
68276262Sgreen{
68376262Sgreen  return lang_hooks.decl_printable_name (node->decl, 2);
68476262Sgreen}
68576262Sgreen
68676262Sgreen/* Return name of the node used in debug output.  */
68792559Sdesstatic const char *
68860573Skriscgraph_varpool_node_name (struct cgraph_varpool_node *node)
68960573Skris{
69060573Skris  return lang_hooks.decl_printable_name (node->decl, 2);
69160573Skris}
69260573Skris
69360573Skris/* Names used to print out the availability enum.  */
69460573Skrisstatic const char * const availability_names[] =
69560573Skris  {"unset", "not_available", "overwrittable", "available", "local"};
69692559Sdes
69792559Sdes/* Dump given cgraph node.  */
69860573Skrisvoid
69992559Sdesdump_cgraph_node (FILE *f, struct cgraph_node *node)
70060573Skris{
70160573Skris  struct cgraph_edge *edge;
70292559Sdes  fprintf (f, "%s/%i:", cgraph_node_name (node), node->uid);
70392559Sdes  if (node->global.inlined_to)
70460573Skris    fprintf (f, " (inline copy in %s/%i)",
70560573Skris	     cgraph_node_name (node->global.inlined_to),
70660573Skris	     node->global.inlined_to->uid);
70760573Skris  if (cgraph_function_flags_ready)
70860573Skris    fprintf (f, " availability:%s",
70960573Skris	     availability_names [cgraph_function_body_availability (node)]);
71060573Skris  if (node->master_clone && node->master_clone->uid != node->uid)
71160573Skris    fprintf (f, "(%i)", node->master_clone->uid);
71260573Skris  if (node->count)
71360573Skris    fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
71492559Sdes	     (HOST_WIDEST_INT)node->count);
71560573Skris  if (node->local.self_insns)
71660573Skris    fprintf (f, " %i insns", node->local.self_insns);
71760573Skris  if (node->global.insns && node->global.insns != node->local.self_insns)
71860573Skris    fprintf (f, " (%i after inlining)", node->global.insns);
71960573Skris  if (node->origin)
72060573Skris    fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
72160573Skris  if (node->needed)
72260573Skris    fprintf (f, " needed");
72360573Skris  else if (node->reachable)
72492559Sdes    fprintf (f, " reachable");
72560573Skris  if (DECL_SAVED_TREE (node->decl))
72660573Skris    fprintf (f, " tree");
72760573Skris  if (node->output)
72860573Skris    fprintf (f, " output");
72960573Skris  if (node->local.local)
73060573Skris    fprintf (f, " local");
73160573Skris  if (node->local.externally_visible)
73276262Sgreen    fprintf (f, " externally_visible");
73360573Skris  if (node->local.finalized)
73460573Skris    fprintf (f, " finalized");
73560573Skris  if (node->local.disregard_inline_limits)
73692559Sdes    fprintf (f, " always_inline");
73760573Skris  else if (node->local.inlinable)
73860573Skris    fprintf (f, " inlinable");
73960573Skris  if (node->local.redefined_extern_inline)
74092559Sdes    fprintf (f, " redefined_extern_inline");
74160573Skris  if (TREE_ASM_WRITTEN (node->decl))
74260573Skris    fprintf (f, " asm_written");
74360573Skris
74460573Skris  fprintf (f, "\n  called by: ");
74560573Skris  for (edge = node->callers; edge; edge = edge->next_caller)
74660573Skris    {
74760573Skris      fprintf (f, "%s/%i ", cgraph_node_name (edge->caller),
74860573Skris	       edge->caller->uid);
74960573Skris      if (edge->count)
75060573Skris	fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
75160573Skris		 (HOST_WIDEST_INT)edge->count);
75292559Sdes      if (!edge->inline_failed)
75360573Skris	fprintf(f, "(inlined) ");
75492559Sdes    }
75592559Sdes
75660573Skris  fprintf (f, "\n  calls: ");
75776262Sgreen  for (edge = node->callees; edge; edge = edge->next_callee)
75876262Sgreen    {
75957429Smarkm      fprintf (f, "%s/%i ", cgraph_node_name (edge->callee),
76060573Skris	       edge->callee->uid);
76192559Sdes      if (!edge->inline_failed)
76260573Skris	fprintf(f, "(inlined) ");
76357429Smarkm      if (edge->count)
76460573Skris	fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
76592559Sdes		 (HOST_WIDEST_INT)edge->count);
76660573Skris      if (edge->loop_nest)
76760573Skris	fprintf (f, "(nested in %i loops) ", edge->loop_nest);
76860573Skris    }
76960573Skris  fprintf (f, "\n");
77060573Skris}
77160573Skris
77260573Skris/* Dump the callgraph.  */
77360573Skris
77492559Sdesvoid
77560573Skrisdump_cgraph (FILE *f)
77660573Skris{
77757429Smarkm  struct cgraph_node *node;
77860573Skris
77992559Sdes  fprintf (f, "callgraph:\n\n");
78060573Skris  for (node = cgraph_nodes; node; node = node->next)
78160573Skris    dump_cgraph_node (f, node);
78257429Smarkm}
78360573Skris
78460573Skris/* Dump given cgraph node.  */
78560573Skrisvoid
78660573Skrisdump_cgraph_varpool_node (FILE *f, struct cgraph_varpool_node *node)
78760573Skris{
78860573Skris  fprintf (f, "%s:", cgraph_varpool_node_name (node));
78960573Skris  fprintf (f, " availability:%s",
79060573Skris	   cgraph_function_flags_ready
79160573Skris	   ? availability_names[cgraph_variable_initializer_availability (node)]
79260573Skris	   : "not-ready");
79360573Skris  if (DECL_INITIAL (node->decl))
79460573Skris    fprintf (f, " initialized");
79560573Skris  if (node->needed)
79660573Skris    fprintf (f, " needed");
79760573Skris  if (node->analyzed)
79860573Skris    fprintf (f, " analyzed");
79960573Skris  if (node->finalized)
80060573Skris    fprintf (f, " finalized");
80160573Skris  if (node->output)
80260573Skris    fprintf (f, " output");
80360573Skris  if (node->externally_visible)
80460573Skris    fprintf (f, " externally_visible");
80560573Skris  fprintf (f, "\n");
80660573Skris}
80760573Skris
80860573Skris/* Dump the callgraph.  */
80960573Skris
81060573Skrisvoid
81157429Smarkmdump_varpool (FILE *f)
81292559Sdes{
81360573Skris  struct cgraph_varpool_node *node;
81460573Skris
81592559Sdes  fprintf (f, "variable pool:\n\n");
81660573Skris  for (node = cgraph_varpool_nodes; node; node = node->next_needed)
81760573Skris    dump_cgraph_varpool_node (f, node);
81860573Skris}
81960573Skris
82060573Skris/* Returns a hash code for P.  */
82160573Skris
82260573Skrisstatic hashval_t
82360573Skrishash_varpool_node (const void *p)
82460573Skris{
82576262Sgreen  const struct cgraph_varpool_node *n = (const struct cgraph_varpool_node *) p;
82660573Skris  return (hashval_t) DECL_UID (n->decl);
82760573Skris}
82892559Sdes
82960573Skris/* Returns nonzero if P1 and P2 are equal.  */
83060573Skris
83160573Skrisstatic int
83260573Skriseq_varpool_node (const void *p1, const void *p2)
83360573Skris{
83460573Skris  const struct cgraph_varpool_node *n1 =
83560573Skris    (const struct cgraph_varpool_node *) p1;
83657429Smarkm  const struct cgraph_varpool_node *n2 =
83792559Sdes    (const struct cgraph_varpool_node *) p2;
83860573Skris  return DECL_UID (n1->decl) == DECL_UID (n2->decl);
83960573Skris}
84092559Sdes
84192559Sdes/* Return cgraph_varpool node assigned to DECL.  Create new one when needed.  */
84292559Sdesstruct cgraph_varpool_node *
84392559Sdescgraph_varpool_node (tree decl)
84460573Skris{
84560573Skris  struct cgraph_varpool_node key, *node, **slot;
84692559Sdes
84792559Sdes  gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL);
84892559Sdes
84992559Sdes  if (!cgraph_varpool_hash)
85092559Sdes    cgraph_varpool_hash = htab_create_ggc (10, hash_varpool_node,
85192559Sdes					   eq_varpool_node, NULL);
85292559Sdes  key.decl = decl;
85392559Sdes  slot = (struct cgraph_varpool_node **)
85492559Sdes    htab_find_slot (cgraph_varpool_hash, &key, INSERT);
85560573Skris  if (*slot)
85692559Sdes    return *slot;
85760573Skris  node = GGC_CNEW (struct cgraph_varpool_node);
85892559Sdes  node->decl = decl;
85960573Skris  node->order = cgraph_order++;
86060573Skris  node->next = cgraph_varpool_nodes;
86160573Skris  cgraph_varpool_nodes = node;
86257429Smarkm  *slot = node;
86376262Sgreen  return node;
86492559Sdes}
86576262Sgreen
86676262Sgreenstruct cgraph_varpool_node *
86776262Sgreencgraph_varpool_node_for_asm (tree asmname)
86876262Sgreen{
86992559Sdes  struct cgraph_varpool_node *node;
87076262Sgreen
87176262Sgreen  for (node = cgraph_varpool_nodes; node ; node = node->next)
87276262Sgreen    if (decl_assembler_name_equal (node->decl, asmname))
87376262Sgreen      return node;
87476262Sgreen
87576262Sgreen  return NULL;
87676262Sgreen}
87776262Sgreen
87876262Sgreen/* Set the DECL_ASSEMBLER_NAME and update cgraph hashtables.  */
87976262Sgreenvoid
88076262Sgreenchange_decl_assembler_name (tree decl, tree name)
88176262Sgreen{
88276262Sgreen  if (!DECL_ASSEMBLER_NAME_SET_P (decl))
88376262Sgreen    {
88476262Sgreen      SET_DECL_ASSEMBLER_NAME (decl, name);
88576262Sgreen      return;
88676262Sgreen    }
88776262Sgreen  if (name == DECL_ASSEMBLER_NAME (decl))
88876262Sgreen    return;
88976262Sgreen
89076262Sgreen  if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
89176262Sgreen      && DECL_RTL_SET_P (decl))
89276262Sgreen    warning (0, "%D renamed after being referenced in assembly", decl);
89376262Sgreen
89476262Sgreen  SET_DECL_ASSEMBLER_NAME (decl, name);
89576262Sgreen}
89676262Sgreen
89776262Sgreen/* Helper function for finalization code - add node into lists so it will
89876262Sgreen   be analyzed and compiled.  */
89976262Sgreenvoid
90076262Sgreencgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *node)
90176262Sgreen{
90276262Sgreen  if (cgraph_varpool_last_needed_node)
90376262Sgreen    cgraph_varpool_last_needed_node->next_needed = node;
90476262Sgreen  cgraph_varpool_last_needed_node = node;
90576262Sgreen  node->next_needed = NULL;
90676262Sgreen  if (!cgraph_varpool_nodes_queue)
90776262Sgreen    cgraph_varpool_nodes_queue = node;
90876262Sgreen  if (!cgraph_varpool_first_unanalyzed_node)
90976262Sgreen    cgraph_varpool_first_unanalyzed_node = node;
91076262Sgreen  notice_global_symbol (node->decl);
91176262Sgreen}
91276262Sgreen
91376262Sgreen/* Reset the queue of needed nodes.  */
91476262Sgreenvoid
91576262Sgreencgraph_varpool_reset_queue (void)
91692559Sdes{
91776262Sgreen  cgraph_varpool_last_needed_node = NULL;
91876262Sgreen  cgraph_varpool_nodes_queue = NULL;
91976262Sgreen  cgraph_varpool_first_unanalyzed_node = NULL;
92076262Sgreen}
92176262Sgreen
92276262Sgreen/* Notify finalize_compilation_unit that given node is reachable
92376262Sgreen   or needed.  */
92476262Sgreenvoid
92576262Sgreencgraph_varpool_mark_needed_node (struct cgraph_varpool_node *node)
92676262Sgreen{
92776262Sgreen  if (!node->needed && node->finalized
92876262Sgreen      && !TREE_ASM_WRITTEN (node->decl))
92976262Sgreen    cgraph_varpool_enqueue_needed_node (node);
93076262Sgreen  node->needed = 1;
93176262Sgreen}
93276262Sgreen
93376262Sgreen/* Determine if variable DECL is needed.  That is, visible to something
93492559Sdes   either outside this translation unit, something magic in the system
93576262Sgreen   configury, or (if not doing unit-at-a-time) to something we haven't
93676262Sgreen   seen yet.  */
93776262Sgreen
93876262Sgreenbool
93976262Sgreendecide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
94076262Sgreen{
94192559Sdes  /* If the user told us it is used, then it must be so.  */
94276262Sgreen  if (node->externally_visible)
94376262Sgreen    return true;
94476262Sgreen  if (!flag_unit_at_a_time
94576262Sgreen      && lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
94676262Sgreen    return true;
94776262Sgreen
94876262Sgreen  /* ??? If the assembler name is set by hand, it is possible to assemble
94976262Sgreen     the name later after finalizing the function and the fact is noticed
95076262Sgreen     in assemble_name then.  This is arguably a bug.  */
95176262Sgreen  if (DECL_ASSEMBLER_NAME_SET_P (decl)
95276262Sgreen      && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
95376262Sgreen    return true;
95476262Sgreen
95576262Sgreen  /* If we decided it was needed before, but at the time we didn't have
95676262Sgreen     the definition available, then it's still needed.  */
95776262Sgreen  if (node->needed)
95876262Sgreen    return true;
95976262Sgreen
96076262Sgreen  /* Externally visible variables must be output.  The exception is
96192559Sdes     COMDAT variables that must be output only when they are needed.  */
96276262Sgreen  if (TREE_PUBLIC (decl) && !flag_whole_program && !DECL_COMDAT (decl)
96376262Sgreen      && !DECL_EXTERNAL (decl))
96476262Sgreen    return true;
96576262Sgreen
96676262Sgreen  /* When not reordering top level variables, we have to assume that
96776262Sgreen     we are going to keep everything.  */
96876262Sgreen  if (flag_unit_at_a_time && flag_toplevel_reorder)
96976262Sgreen    return false;
97076262Sgreen
97176262Sgreen  /* We want to emit COMDAT variables only when absolutely necessary.  */
97276262Sgreen  if (DECL_COMDAT (decl))
97360573Skris    return false;
97492559Sdes  return true;
97560573Skris}
97660573Skris
97792559Sdesvoid
97860573Skriscgraph_varpool_finalize_decl (tree decl)
97992559Sdes{
98060573Skris  struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
98176262Sgreen
98260573Skris  /* The first declaration of a variable that comes through this function
98357429Smarkm     decides whether it is global (in C, has external linkage)
98460573Skris     or local (in C, has internal linkage).  So do nothing more
98560573Skris     if this function has already run.  */
98660573Skris  if (node->finalized)
98760573Skris    {
98892559Sdes      if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
98992559Sdes	cgraph_varpool_assemble_pending_decls ();
99092559Sdes      return;
99192559Sdes    }
99292559Sdes  if (node->needed)
99360573Skris    cgraph_varpool_enqueue_needed_node (node);
99460573Skris  node->finalized = true;
99560573Skris
99660573Skris  if (decide_is_variable_needed (node, decl))
99792559Sdes    cgraph_varpool_mark_needed_node (node);
99876262Sgreen  /* Since we reclaim unreachable nodes at the end of every language
99960573Skris     level unit, we need to be conservative about possible entry points
100060573Skris     there.  */
100176262Sgreen  else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
100257429Smarkm    cgraph_varpool_mark_needed_node (node);
100392559Sdes  if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
100460573Skris    cgraph_varpool_assemble_pending_decls ();
100560573Skris}
100669587Sgreen
100760573Skris/* Add a top-level asm statement to the list.  */
100860573Skris
100960573Skrisstruct cgraph_asm_node *
101092559Sdescgraph_add_asm_node (tree asm_str)
101192559Sdes{
101292559Sdes  struct cgraph_asm_node *node;
101376262Sgreen
101476262Sgreen  node = GGC_CNEW (struct cgraph_asm_node);
101560573Skris  node->asm_str = asm_str;
101660573Skris  node->order = cgraph_order++;
101757429Smarkm  node->next = NULL;
101860573Skris  if (cgraph_asm_nodes == NULL)
101957429Smarkm    cgraph_asm_nodes = node;
102060573Skris  else
102160573Skris    cgraph_asm_last_node->next = node;
102260573Skris  cgraph_asm_last_node = node;
102392559Sdes  return node;
102492559Sdes}
102592559Sdes
102692559Sdes/* Return true when the DECL can possibly be inlined.  */
102760573Skrisbool
102857429Smarkmcgraph_function_possibly_inlined_p (tree decl)
102976262Sgreen{
103057429Smarkm  if (!cgraph_global_info_ready)
103157429Smarkm    return (DECL_INLINE (decl) && !flag_really_no_inline);
103257429Smarkm  return DECL_POSSIBLY_INLINED (decl);
103392559Sdes}
103476262Sgreen
103576262Sgreen/* Create clone of E in the node N represented by CALL_EXPR the callgraph.  */
103676262Sgreenstruct cgraph_edge *
103776262Sgreencgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
103876262Sgreen		   tree call_stmt, gcov_type count_scale, int loop_nest,
103976262Sgreen		   bool update_original)
104076262Sgreen{
104176262Sgreen  struct cgraph_edge *new;
104276262Sgreen
104376262Sgreen  new = cgraph_create_edge (n, e->callee, call_stmt,
104476262Sgreen			    e->count * count_scale / REG_BR_PROB_BASE,
104576262Sgreen			    e->loop_nest + loop_nest);
104676262Sgreen
104776262Sgreen  new->inline_failed = e->inline_failed;
104876262Sgreen  if (update_original)
104976262Sgreen    {
105076262Sgreen      e->count -= new->count;
105176262Sgreen      if (e->count < 0)
105276262Sgreen	e->count = 0;
105376262Sgreen    }
105476262Sgreen  return new;
105576262Sgreen}
105676262Sgreen
105776262Sgreen/* Create node representing clone of N executed COUNT times.  Decrease
105876262Sgreen   the execution counts from original node too.
105976262Sgreen
106076262Sgreen   When UPDATE_ORIGINAL is true, the counts are subtracted from the original
106176262Sgreen   function's profile to reflect the fact that part of execution is handled
106276262Sgreen   by node.  */
106376262Sgreenstruct cgraph_node *
106476262Sgreencgraph_clone_node (struct cgraph_node *n, gcov_type count, int loop_nest,
106576262Sgreen		   bool update_original)
106676262Sgreen{
106776262Sgreen  struct cgraph_node *new = cgraph_create_node ();
106876262Sgreen  struct cgraph_edge *e;
106976262Sgreen  gcov_type count_scale;
107076262Sgreen
107176262Sgreen  new->decl = n->decl;
107276262Sgreen  new->origin = n->origin;
107376262Sgreen  if (new->origin)
107476262Sgreen    {
107576262Sgreen      new->next_nested = new->origin->nested;
107692559Sdes      new->origin->nested = new;
107792559Sdes    }
107876262Sgreen  new->analyzed = n->analyzed;
107976262Sgreen  new->local = n->local;
108076262Sgreen  new->global = n->global;
108176262Sgreen  new->rtl = n->rtl;
108276262Sgreen  new->master_clone = n->master_clone;
108376262Sgreen  new->count = count;
108457429Smarkm  if (n->count)
108560573Skris    count_scale = new->count * REG_BR_PROB_BASE / n->count;
108657429Smarkm  else
108792559Sdes    count_scale = 0;
108860573Skris  if (update_original)
108957429Smarkm    {
109076262Sgreen      n->count -= count;
109157429Smarkm      if (n->count < 0)
109292559Sdes	n->count = 0;
109357429Smarkm    }
109476262Sgreen
109557429Smarkm  for (e = n->callees;e; e=e->next_callee)
109660573Skris    cgraph_clone_edge (e, new, e->call_stmt, count_scale, loop_nest,
109760573Skris		       update_original);
109860573Skris
109960573Skris  new->next_clone = n->next_clone;
110076262Sgreen  new->prev_clone = n;
110192559Sdes  n->next_clone = new;
110292559Sdes  if (new->next_clone)
110392559Sdes    new->next_clone->prev_clone = new;
110492559Sdes
110592559Sdes  return new;
110692559Sdes}
110792559Sdes
110892559Sdes/* Return true if N is an master_clone, (see cgraph_master_clone).  */
110992559Sdes
111092559Sdesbool
111192559Sdescgraph_is_master_clone (struct cgraph_node *n)
111292559Sdes{
111376262Sgreen  return (n == cgraph_master_clone (n));
111460573Skris}
111560573Skris
111660573Skrisstruct cgraph_node *
111760573Skriscgraph_master_clone (struct cgraph_node *n)
111860573Skris{
111960573Skris  enum availability avail = cgraph_function_body_availability (n);
112092559Sdes
112192559Sdes  if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
112276262Sgreen    return NULL;
112360573Skris
112476262Sgreen  if (!n->master_clone)
112576262Sgreen    n->master_clone = cgraph_node (n->decl);
112676262Sgreen
112776262Sgreen  return n->master_clone;
112876262Sgreen}
112992559Sdes
113092559Sdes/* NODE is no longer nested function; update cgraph accordingly.  */
113192559Sdesvoid
113292559Sdescgraph_unnest_node (struct cgraph_node *node)
113392559Sdes{
113492559Sdes  struct cgraph_node **node2 = &node->origin->nested;
113592559Sdes  gcc_assert (node->origin);
113692559Sdes
113776262Sgreen  while (*node2 != node)
113892559Sdes    node2 = &(*node2)->next_nested;
113960573Skris  *node2 = node->next_nested;
114060573Skris  node->origin = NULL;
114157429Smarkm}
114260573Skris
114360573Skris/* Return function availability.  See cgraph.h for description of individual
114460573Skris   return values.  */
114560573Skrisenum availability
114692559Sdescgraph_function_body_availability (struct cgraph_node *node)
114760573Skris{
114860573Skris  enum availability avail;
114992559Sdes  gcc_assert (cgraph_function_flags_ready);
115092559Sdes  if (!node->analyzed)
115192559Sdes    avail = AVAIL_NOT_AVAILABLE;
115260573Skris  else if (node->local.local)
115360573Skris    avail = AVAIL_LOCAL;
115457429Smarkm  else if (node->local.externally_visible)
115560573Skris    avail = AVAIL_AVAILABLE;
115660573Skris
115760573Skris  /* If the function can be overwritten, return OVERWRITABLE.  Take
115860573Skris     care at least of two notable extensions - the COMDAT functions
115960573Skris     used to share template instantiations in C++ (this is symmetric
116060573Skris     to code cp_cannot_inline_tree_fn and probably shall be shared and
116160573Skris     the inlinability hooks completely eliminated).
116292559Sdes
116392559Sdes     ??? Does the C++ one definition rule allow us to always return
116476262Sgreen     AVAIL_AVAILABLE here?  That would be good reason to preserve this
116576262Sgreen     hook Similarly deal with extern inline functions - this is again
116692559Sdes     necessary to get C++ shared functions having keyed templates
116776262Sgreen     right and in the C extension documentation we probably should
116876262Sgreen     document the requirement of both versions of function (extern
116976262Sgreen     inline and offline) having same side effect characteristics as
117092559Sdes     good optimization is what this optimization is about.  */
117176262Sgreen
117276262Sgreen  else if (!(*targetm.binds_local_p) (node->decl)
117376262Sgreen	   && !DECL_COMDAT (node->decl) && !DECL_EXTERNAL (node->decl))
117476262Sgreen    avail = AVAIL_OVERWRITABLE;
117592559Sdes  else avail = AVAIL_AVAILABLE;
117676262Sgreen
117760573Skris  return avail;
117860573Skris}
117960573Skris
118057429Smarkm/* Return variable availability.  See cgraph.h for description of individual
118192559Sdes   return values.  */
118276262Sgreenenum availability
118376262Sgreencgraph_variable_initializer_availability (struct cgraph_varpool_node *node)
118492559Sdes{
118592559Sdes  gcc_assert (cgraph_function_flags_ready);
118692559Sdes  if (!node->finalized)
118776262Sgreen    return AVAIL_NOT_AVAILABLE;
118892559Sdes  if (!TREE_PUBLIC (node->decl))
118992559Sdes    return AVAIL_AVAILABLE;
119092559Sdes  /* If the variable can be overwritten, return OVERWRITABLE.  Takes
119192559Sdes     care of at least two notable extensions - the COMDAT variables
119292559Sdes     used to share template instantiations in C++.  */
119392559Sdes  if (!(*targetm.binds_local_p) (node->decl) && !DECL_COMDAT (node->decl))
119492559Sdes    return AVAIL_OVERWRITABLE;
119592559Sdes  return AVAIL_AVAILABLE;
119692559Sdes}
119792559Sdes
119892559Sdes
119992559Sdes/* Add the function FNDECL to the call graph.  FNDECL is assumed to be
120092559Sdes   in low GIMPLE form and ready to be processed by cgraph_finalize_function.
120192559Sdes
120292559Sdes   When operating in unit-at-a-time, a new callgraph node is added to
120392559Sdes   CGRAPH_EXPAND_QUEUE, which is processed after all the original
120492559Sdes   functions in the call graph .
120592559Sdes
120676262Sgreen   When not in unit-at-a-time, the new callgraph node is added to
120792559Sdes   CGRAPH_NODES_QUEUE for cgraph_assemble_pending_functions to
120892559Sdes   process.  */
120992559Sdes
121092559Sdesvoid
121192559Sdescgraph_add_new_function (tree fndecl)
121292559Sdes{
121392559Sdes  struct cgraph_node *n = cgraph_node (fndecl);
121492559Sdes  n->next_needed = cgraph_expand_queue;
121592559Sdes  cgraph_expand_queue = n;
121692559Sdes}
121776262Sgreen
121892559Sdes#include "gt-cgraph.h"
121992559Sdes