> 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