> Hello, > following patch introduces a new symbol_table class, encapsulating > functions related to symbol table management. Apart from that, cgraph_edge > related functions become members of the class. Finally, a portion of clean-up > has been applied to cgraph.h. > > Bootstrapped on x86_64-pc-linux-gnu and majority of BEs have been tested for > C and C++, no regression observed. > > Thank you, > Martin > > - if (!used_as_abstract_origin && cgraph_state != CGRAPH_STATE_PARSING) > + if (!used_as_abstract_origin && symtab->state != CGRAPH_STATE_PARSING)
I would probably rename this CGRAPH_ enum into SYMTAB. Given it is a symtab state now ;) > > struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) > cgraph_edge { > + /* Remove the edge in the cgraph. */ > + void remove (void); > + > + /* Remove the edge from the list of the callers of the callee. */ > + void remove_caller (void); > + > + /* Remove the edge from the list of the callees of the caller. */ > + void remove_callee (void); Perhaps those two can become private? > + > + /* Change field call_stmt of edge to NEW_STMT. > + If UPDATE_SPECULATIVE and E is any component of speculative > + edge, then update all components. */ > + void set_call_stmt (gimple new_stmt, bool update_speculative = true); > + > + /* Redirect callee of the edge to N. The function does not update > underlying > + call expression. */ > + void redirect_callee (cgraph_node *n); > + > + /* Make an indirect edge with an unknown callee an ordinary edge leading to > + CALLEE. DELTA is an integer constant that is to be added to the this > + pointer (first parameter) to compensate for skipping > + a thunk adjustment. */ > + cgraph_edge *make_direct (cgraph_node *callee); > + > + /* Turn edge into speculative call calling N2. Update > + the profile so the direct call is taken COUNT times > + with FREQUENCY. */ > + cgraph_edge *turn_to_speculative (cgraph_node *n2, gcov_type direct_count, > + int direct_frequency); Porably make_speculative (like make_direct). > + > + /* If necessary, change the function declaration in the call statement > + associated with the edge so that it corresponds to the edge callee. */ > + gimple redirect_call_stmt_to_callee (void); > + > + /* Given speculative call edge, return all three components. */ > + void speculative_call_info (cgraph_edge *&direct, cgraph_edge *&indirect, > + ipa_ref *&reference); > + > + /* Create clone of edge in the node N represented > + by CALL_EXPR the callgraph. */ > + cgraph_edge * clone (cgraph_node *n, gimple call_stmt, unsigned stmt_uid, > + gcov_type count_scale, int freq_scale, bool > update_original); > + > + /* Speculative call edge turned out to be direct call to CALLE_DECL. > + Remove the speculative call sequence and return edge representing the > call. > + It is up to caller to redirect the call as appropriate. */ > + cgraph_edge *resolve_speculation (tree callee_decl = NULL); Probably better to group speculation into one block. > + > + /* Return true when call of edge can not lead to return from caller > + and thus it is safe to ignore its side effects for IPA analysis > + when computing side effects of the caller. */ > + bool cannot_lead_to_return_p (void); > + > + /* Return true when the edge represents a direct recursion. */ > + bool recursive_p (void); > + > + /* Return true if the call can be hot. */ > + bool maybe_hot_p (void); > + > + > + /* Perform reachability analysis and reclaim all unreachable nodes. */ > + bool remove_unreachable_nodes (bool before_inlining_p, FILE *file); > + > + /* Optimization of function bodies might've rendered some variables as > + unnecessary so we want to avoid these from being compiled. Re-do > + reachability starting from variables that are either externally visible > + or was referred from the asm output routines. */ > + void remove_unreferenced_decls (void); > + > + /* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these > + functions into callgraph in a way so they look like ordinary reachable > + functions inserted into callgraph already at construction time. */ > + void process_new_functions (void); > + > + /* C++ frontend produce same body aliases all over the place, even before > PCH > + gets streamed out. It relies on us linking the aliases with their > function > + in order to do the fixups, but ipa-ref is not PCH safe. Consequentely > we > + first produce aliases without links, but once C++ FE is sure he won't > sream > + PCH we build the links via this function. */ > + void process_same_body_aliases (void); > + > + /* Output all variables enqueued to be assembled. */ > + bool output_variables (void); > + > + /* Output all asm statements we have stored up to be output. */ > + void output_asm_statements (void); > + > + /* Analyze the whole compilation unit once it is parsed completely. */ > + void finalize_compilation_unit (void); > + > + /* Perform simple optimizations based on callgraph. */ > + void compile (void); It would make sense to order this in a way compilation flows, that is first finalize_* stuff (since that is used by FA) ending by finalize_compilation_unit and process_same_body_aliases, then compile, add_new* stuff, process_new* and then output_*/asemble_* stuff. > + > + /* Weakrefs may be associated to external decls and thus not output > + at expansion time. Emit all necessary aliases. */ > + void output_weakrefs (void); > + > + /* Unregister a symbol NODE. */ > + inline void unregister (symtab_node *node); > + > + /* Allocate new callgraph node and insert it into basic data structures. > */ > + cgraph_node *create_empty (void); > + > + void release_symbol (cgraph_node *node, int uid); Missing comment. > + > + /* Allocate new callgraph node. */ > + inline cgraph_node * allocate_cgraph_symbol (void); There may be chance to friend those four into symtab_node making it clear they are internal bookkeping issues? > + > + /* Return first static symbol with definition. */ > + inline symtab_node *first_symbol (void); > + > + inline asm_node * > + first_asm_symbol (void) > + { > + return asmnodes; > + } > + > + /* Return first static symbol with definition. */ > + inline symtab_node *first_defined_symbol (void); > + > + /* Return first variable. */ > + inline varpool_node *first_variable (void); > + > + /* Return next variable after NODE. */ > + inline varpool_node *next_variable (varpool_node *node); > + > + /* Return first static variable with initializer. */ > + inline varpool_node *first_static_initializer (void); > + > + /* Return next static variable with initializer after NODE. */ > + inline varpool_node *next_static_initializer (varpool_node *node); > + > + /* Return first static variable with definition. */ > + inline varpool_node *first_defined_variable (void); > + > + /* Return next static variable with definition after NODE. */ > + inline varpool_node *next_defined_variable (varpool_node *node); > + > + /* Return first function with body defined. */ > + inline cgraph_node *first_defined_function (void); > + > + /* Return next function with body defined after NODE. */ > + inline cgraph_node *next_defined_function (cgraph_node *node); > + > + /* Return first function. */ > + inline cgraph_node *first_function (void); > + > + /* Return next function. */ > + inline cgraph_node *next_function (cgraph_node *node); > + > + /* Return first function with body defined. */ > + cgraph_node *first_function_with_gimple_body (void); > + > + /* Allocate a cgraph_edge structure and fill it with data according to the > + parameters of which only CALLEE can be NULL (when creating an indirect > call > + edge). */ > + cgraph_edge *create_edge (cgraph_node *caller, cgraph_node *callee, > + gimple call_stmt, gcov_type count, int freq, > + bool indir_unknown_callee); I would expect create_edge to be method of caller.... > + > + /* Put the edge onto the free list. */ > + void free_edge (cgraph_edge *e); Also perhaps hidding from general interface with friend. Definitely put it to the end of function list. > + > + /* Return next reachable static variable with initializer after NODE. */ > + inline cgraph_node *next_function_with_gimple_body (cgraph_node *node); > + > + cgraph_edge_hook_list *add_edge_removal_hook (cgraph_edge_hook, void *); > + void remove_edge_removal_hook (cgraph_edge_hook_list *); > + > + cgraph_node_hook_list *add_cgraph_removal_hook (cgraph_node_hook, void *); > + void remove_cgraph_removal_hook (cgraph_node_hook_list *); > + > + varpool_node_hook_list *add_varpool_removal_hook (varpool_node_hook, > + void *); > + void remove_varpool_removal_hook (varpool_node_hook_list *); > + cgraph_node_hook_list *add_cgraph_insertion_hook (cgraph_node_hook, > + void *); > + > + void remove_cgraph_insertion_hook (cgraph_node_hook_list *); > + varpool_node_hook_list *add_varpool_insertion_hook (varpool_node_hook, > + void *); > + void remove_varpool_insertion_hook (varpool_node_hook_list *); > + cgraph_2edge_hook_list *add_edge_duplication_hook (cgraph_2edge_hook, void > *); > + void remove_edge_duplication_hook (cgraph_2edge_hook_list *); > + > + cgraph_2node_hook_list *add_cgraph_duplication_hook (cgraph_2node_hook, > + void *); > + void remove_cgraph_duplication_hook (cgraph_2node_hook_list *); Add comments. > + > + /* Call all edge removal hooks. */ > + void call_edge_removal_hooks (cgraph_edge *e); > + > + /* Call all node insertion hooks. */ > + void call_cgraph_insertion_hooks (cgraph_node *node); > + > + /* Call all node removal hooks. */ > + void call_cgraph_removal_hooks (cgraph_node *node); > + > + /* Call all node duplication hooks. */ > + void call_cgraph_duplication_hooks (cgraph_node *node, cgraph_node *node2); > + > + /* Call all edge duplication hooks. */ > + void call_edge_duplication_hooks (cgraph_edge *cs1, cgraph_edge *cs2); > + > + /* Call all node removal hooks. */ > + void call_varpool_removal_hooks (varpool_node *node); > + > + /* Call all node insertion hooks. */ > + void call_varpool_insertion_hooks (varpool_node *node); > + > + /* Insert NODE to assembler name hash. */ > + void insert_to_assembler_name_hash (symtab_node *node, bool with_clones); > + > + /* Remove NODE from assembler name hash. */ > + void unlink_from_assembler_name_hash (symtab_node *node, bool with_clones); Again internal bookkeeping, should go to end and ideally be friend, but I guess this one is used by lto-symtab. (I amy clean it up incrementally) > + > + /* Arrange node to be first in its entry of assembler_name_hash. */ > + void symtab_prevail_in_asm_name_hash (symtab_node *node); > + > + /* Initalize asm name hash unless. */ > + void symtab_initialize_asm_name_hash (void); > + > + /* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */ > + void change_decl_assembler_name (tree decl, tree name); > + > + /* Rebuild cgraph edges for current function node. This needs to be run > after > + passes that don't update the cgraph. */ > + unsigned int rebuild_edges (void); This ought to be method of cgraph_edge. > + > + /* Rebuild cgraph references for current function node. This needs to be > run > + after passes that don't update the cgraph. */ > + void rebuild_references (void); LIke here. > + > + /* Once all functions from compilation unit are in memory, produce all > clones > + and update all calls. We might also do this on demand if we don't want > to > + bring all functions to memory prior compilation, but current WHOPR > + implementation does that and it is is bit easier to keep everything > right > + in this order. */ > + void materialize_all_clones (void); > + > + /* Hash asmnames ignoring the user specified marks. */ > + static hashval_t decl_assembler_name_hash (const_tree asmname); > + > + /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */ > + static bool decl_assembler_name_equal (tree decl, const_tree asmname); > + > + /* Returns a hash code for P. */ > + static hashval_t hash_node_by_assembler_name (const void *p); > + > + /* Returns nonzero if P1 and P2 are equal. */ > + static int eq_assembler_name (const void *p1, const void *p2); Private? > + > + int cgraph_count; > + int cgraph_max_uid; > > -/* In symtab.c */ > -symtab_node *symtab_node_for_asm (const_tree asmname); > + int edges_count; > + int edges_max_uid; > + > + symtab_node* GTY(()) nodes; > + asm_node* GTY(()) asmnodes; > + asm_node* GTY(()) asm_last_node; > + cgraph_node* GTY(()) free_nodes; > + > + /* Head of a linked list of unused (freed) call graph edges. > + Do not GTY((delete)) this list so UIDs gets reliably recycled. */ > + cgraph_edge * GTY(()) free_edges; > + > + /* The order index of the next symtab node to be created. This is > + used so that we can sort the cgraph nodes in order by when we saw > + them, to support -fno-toplevel-reorder. */ > + int order; > + > + /* Set when whole unit has been analyzed so we can access global info. */ > + bool global_info_ready; > + /* What state callgraph is in right now. */ > + enum cgraph_state state; > + /* Set when the cgraph is fully build and the basic flags are computed. */ > + bool function_flags_ready; > + > + bool cpp_implicit_aliases_done; Good they are grouped together. Perhaps they all can be part of STATE (as a followup) Thanks, Honza