From 2dc9831fc1c17840efc629788027aeededa44d2f Mon Sep 17 00:00:00 2001 From: crowl Date: Wed, 31 Oct 2012 23:15:10 +0000 Subject: This patch implements generic type query and conversion functions, and applies them to the use of cgraph_node, varpool_node, and symtab_node. The functions are: bool is_a (pointer) Tests whether the pointer actually points to a more derived TYPE. TYPE *as_a (pointer) Converts pointer to a TYPE*. TYPE *dyn_cast (pointer) Converts pointer to TYPE* if and only if "is_a pointer". Otherwise, returns NULL. This function is essentially a checked down cast. These functions reduce compile time and increase type safety when treating a generic item as a more specific item. In essence, the code change is from if (symtab_function_p (node)) { struct cgraph_node *cnode = cgraph (node); .... } to if (cgraph_node *cnode = dyn_cast (node)) { .... } The necessary conditional test defines a variable that holds a known good pointer to the specific item and avoids subsequent conversion calls and the assertion checks that may come with them. When, the property test is embedded within a larger condition, the variable declaration gets pulled out of the condition. (This leaves some room for using the variable inappropriately.) if (symtab_variable_p (node) && varpool (node)->finalized) varpool_analyze_node (varpool (node)); becomes varpool_node *vnode = dyn_cast (node); if (vnode && vnode->finalized) varpool_analyze_node (vnode); Note that we have converted two sets of assertions in the calls to varpool into safe and efficient use of a variable. There are remaining calls to symtab_function_p and symtab_variable_p that do not involve a pointer to a more specific type. These have been converted to calls to a functions is_a and is_a . The original predicate functions have been removed. The cgraph.h header defined both a struct and a function with the name varpool_node. This name overloading can cause some unintuitive error messages when, as is common in C++, one omits the struct keyword when using the type. I have renamed the function to varpool_node_for_decl. Tested on x86_64. Index: gcc/ChangeLog 2012-10-31 Lawrence Crowl * is-a.h: New. (is_a (U*)): New. Test for is-a relationship. (as_a (U*)): New. Treat as a derived type. (dyn_cast (U*)): New. Conditionally cast based on is_a. * cgraph.h (varpool_node): Rename to varpool_node_for_decl. Adjust callers to match. (is_a_helper ::test (symtab_node_def *)): New. (is_a_helper ::test (symtab_node_def *)): New. (symtab_node_def::try_function): New. Change most calls to symtab_function_p with calls to dyn_cast (p). (symtab_node_def::try_variable): New. Change most calls to symtab_variable_p with calls to dyn_cast (p). (symtab_function_p): Remove. Change callers to use is_a (p) instead. (symtab_variable_p): Remove. Change callers to use is_a (p) instead. * cgraph.c (cgraph_node_for_asm): Remove redundant call to symtab_node_for_asm. * cgraphunit.c (symbol_finalized_and_needed): New. (symbol_finalized): New. (cgraph_analyze_functions): Split complicated conditionals out into above new functions. * Makefile.in (CGRAPH_H): Add is-a.h as used by cgraph.h. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@193051 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cgraphunit.c | 91 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 35 deletions(-) (limited to 'gcc/cgraphunit.c') diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 64460ac63b7..230125c4a69 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -386,7 +386,8 @@ referred_to_p (symtab_node node) if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref)) return true; /* For functions check also calls. */ - if (symtab_function_p (node) && cgraph (node)->callers) + cgraph_node *cn = dyn_cast (node); + if (cn && cn->callers) return true; return false; } @@ -809,7 +810,7 @@ process_function_and_variable_attributes (struct cgraph_node *first, void varpool_finalize_decl (tree decl) { - struct varpool_node *node = varpool_node (decl); + struct varpool_node *node = varpool_node_for_decl (decl); gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); @@ -836,6 +837,35 @@ varpool_finalize_decl (tree decl) varpool_assemble_decl (node); } + +/* Determine if a symbol NODE is finalized and needed. */ + +inline static bool +symbol_finalized_and_needed (symtab_node node) +{ + if (cgraph_node *cnode = dyn_cast (node)) + return cnode->local.finalized + && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl); + if (varpool_node *vnode = dyn_cast (node)) + return vnode->finalized + && !DECL_EXTERNAL (vnode->symbol.decl) + && decide_is_variable_needed (vnode, vnode->symbol.decl); + return false; +} + +/* Determine if a symbol NODE is finalized. */ + +inline static bool +symbol_finalized (symtab_node node) +{ + if (cgraph_node *cnode= dyn_cast (node)) + return cnode->local.finalized; + if (varpool_node *vnode = dyn_cast (node)) + return vnode->finalized; + return false; +} + + /* Discover all functions and variables that are trivially needed, analyze them as well as all functions and variables referred by them */ @@ -870,13 +900,7 @@ cgraph_analyze_functions (void) node != (symtab_node)first_analyzed && node != (symtab_node)first_analyzed_var; node = node->symbol.next) { - if ((symtab_function_p (node) - && cgraph (node)->local.finalized - && cgraph_decide_is_function_needed (cgraph (node), node->symbol.decl)) - || (symtab_variable_p (node) - && varpool (node)->finalized - && !DECL_EXTERNAL (node->symbol.decl) - && decide_is_variable_needed (varpool (node), node->symbol.decl))) + if (symbol_finalized_and_needed (node)) { enqueue_node (node); if (!changed && cgraph_dump_file) @@ -903,18 +927,15 @@ cgraph_analyze_functions (void) changed = true; node = first; first = (symtab_node)first->symbol.aux; - if (symtab_function_p (node) && cgraph (node)->local.finalized) + cgraph_node *cnode = dyn_cast (node); + if (cnode && cnode->local.finalized) { struct cgraph_edge *edge; - struct cgraph_node *cnode; - tree decl; - - cnode = cgraph (node); - decl = cnode->symbol.decl; + tree decl = cnode->symbol.decl; - /* ??? It is possible to create extern inline function and later using - weak alias attribute to kill its body. See - gcc.c-torture/compile/20011119-1.c */ + /* ??? It is possible to create extern inline function + and later using weak alias attribute to kill its body. + See gcc.c-torture/compile/20011119-1.c */ if (!DECL_STRUCT_FUNCTION (decl) && (!cnode->alias || !cnode->thunk.alias) && !cnode->thunk.thunk_p) @@ -929,23 +950,25 @@ cgraph_analyze_functions (void) for (edge = cnode->callees; edge; edge = edge->next_callee) if (edge->callee->local.finalized) - enqueue_node ((symtab_node)edge->callee); + enqueue_node ((symtab_node)edge->callee); - /* If decl is a clone of an abstract function, mark that abstract - function so that we don't release its body. The DECL_INITIAL() of that - abstract function declaration will be later needed to output debug - info. */ + /* If decl is a clone of an abstract function, + mark that abstract function so that we don't release its body. + The DECL_INITIAL() of that abstract function declaration + will be later needed to output debug info. */ if (DECL_ABSTRACT_ORIGIN (decl)) { - struct cgraph_node *origin_node; - origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl)); + struct cgraph_node *origin_node + = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl)); origin_node->abstract_and_needed = true; } - } - else if (symtab_variable_p (node) - && varpool (node)->finalized) - varpool_analyze_node (varpool (node)); + else + { + varpool_node *vnode = dyn_cast (node); + if (vnode && vnode->finalized) + varpool_analyze_node (vnode); + } if (node->symbol.same_comdat_group) { @@ -956,8 +979,7 @@ cgraph_analyze_functions (void) enqueue_node (next); } for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) - if ((symtab_function_p (ref->referred) && cgraph (ref->referred)->local.finalized) - || (symtab_variable_p (ref->referred) && varpool (ref->referred)->finalized)) + if (symbol_finalized (ref->referred)) enqueue_node (ref->referred); cgraph_process_new_functions (); } @@ -985,10 +1007,9 @@ cgraph_analyze_functions (void) symtab_remove_node (node); continue; } - if (symtab_function_p (node)) + if (cgraph_node *cnode = dyn_cast (node)) { tree decl = node->symbol.decl; - struct cgraph_node *cnode = cgraph (node); if (cnode->local.finalized && !gimple_has_body_p (decl) && (!cnode->alias || !cnode->thunk.alias) @@ -1070,7 +1091,7 @@ handle_alias_pairs (void) } if (TREE_CODE (p->decl) == FUNCTION_DECL - && target_node && symtab_function_p (target_node)) + && target_node && is_a (target_node)) { struct cgraph_node *src_node = cgraph_get_node (p->decl); if (src_node && src_node->local.finalized) @@ -1079,7 +1100,7 @@ handle_alias_pairs (void) VEC_unordered_remove (alias_pair, alias_pairs, i); } else if (TREE_CODE (p->decl) == VAR_DECL - && target_node && symtab_variable_p (target_node)) + && target_node && is_a (target_node)) { varpool_create_variable_alias (p->decl, target_node->symbol.decl); VEC_unordered_remove (alias_pair, alias_pairs, i); -- cgit v1.2.3