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