From patchwork Wed Oct 31 23:17:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lawrence Crowl X-Patchwork-Id: 196047 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id CFFC92C00B4 for ; Thu, 1 Nov 2012 10:17:34 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1352330255; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:Received:In-Reply-To:References:Date: Message-ID:Subject:From:To:Cc:Content-Type:Mailing-List: Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:Sender:Delivered-To; bh=+OzkrcUAKZYeQUhKnFnp989vbmw=; b=LYcqhKhJ2XrDc80PoZw8Xd2ISxyaPurIKDUYvGacFYAyFiEuDAIDA9niTmsYtz +ZNkhkprnY10dAeBS4iEc686LXNC27stjHlBepzYiSz2C0Kj2Pax5GM8Um0DQofI lKECDeFG1j/PVzSgKCKCbQ84uSmZQ4jtySnPmFJSm0H7E= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:X-Google-DKIM-Signature:MIME-Version:Received:Received:In-Reply-To:References:Date:Message-ID:Subject:From:To:Cc:Content-Type:X-System-Of-Record:X-Gm-Message-State:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=TYC1T0KchcXuymExXwv+MTKVesfiAKD6VxxqeufWjonA9M8e3Lw3AXdExLzsR7 OeEbCUO6q841PdeWMyZyCz+ePajyUKYo0la6BznedPp2We+ZPk6PrZc3Qi0/1Xeu wlD0JYCOmatOGjdWQd5S2KMSd5qoNR/5SMkYl6uhBoLs0=; Received: (qmail 11799 invoked by alias); 31 Oct 2012 23:17:23 -0000 Received: (qmail 11750 invoked by uid 22791); 31 Oct 2012 23:17:19 -0000 X-SWARE-Spam-Status: No, hits=-5.5 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KAM_STOCKGEN, KHOP_RCVD_TRUST, KHOP_THREADED, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RP_MATCHES_RCVD, TW_TM X-Spam-Check-By: sourceware.org Received: from mail-ie0-f175.google.com (HELO mail-ie0-f175.google.com) (209.85.223.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 31 Oct 2012 23:17:05 +0000 Received: by mail-ie0-f175.google.com with SMTP id c13so3184603ieb.20 for ; Wed, 31 Oct 2012 16:17:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:x-system-of-record:x-gm-message-state; bh=HYGCIpWPTkzcrMVLghUQ60dwhgMP/Jt8JHUBPqUyjJ4=; b=aISfJ3Bu+Naq0ggvGllNFrCiMDuWSbCtEMgSqDOYokRkhrYfNUjGx0ZwUB9nr5upmL 2ebvnyVqCO/+9nF65HpvhwQ8SGQcU4G8UpVBgyromrUQcK5UuJ3CC3R+cZ64lFvY92uO jnei2BATktc8p+dfSIDgu7pjwXxw8XlvB+oNEFvTz/QfLLjR47Czmf3JLy9VynMaLqlf sj+DXUj1SgIixMxEGCSJmBnr6p6V4vu03dElIX0ielOcsGPY2QtKNPWD9x928e+JbVO5 BTSH7Psi1+pQJeVKG/OU+Zcfbamk6hfyQLTLqCAXQQndBRFbbVekRhDfnTNrVAlnaz8G 4VgA== MIME-Version: 1.0 Received: by 10.50.188.225 with SMTP id gd1mr3237669igc.15.1351725423960; Wed, 31 Oct 2012 16:17:03 -0700 (PDT) Received: by 10.231.72.19 with HTTP; Wed, 31 Oct 2012 16:17:03 -0700 (PDT) In-Reply-To: References: <508FC625.3050000@google.com> Date: Wed, 31 Oct 2012 16:17:03 -0700 Message-ID: Subject: Re: [patch] Apply conditional down cast to cgraph.h et.al. From: Lawrence Crowl To: Diego Novillo Cc: Marc Glisse , gcc-patches List , Jan Hubicka , Richard Biener X-System-Of-Record: true X-Gm-Message-State: ALoCoQn9AdgSb+ru3OIVWgFX+s5bJJWmzLTTMD6i6Cu2YN0sGlJjvbYeEWwPSQffXyzzY+Rocj4UAe6wsVYdUyX9MuNpjqtVj0uIWdBXv6L7lvIAAntMdLC58xNSA7x10mazSzB9tMHmLQmm8TdNNEKalpokHt1+WOwV65XU0Eb3ImuI4H350Uoi2XN4xa7Kw6aX9FugWL+f X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org On 10/30/12, Lawrence Crowl wrote: > On 10/30/12, Diego Novillo wrote: >> On Tue, Oct 30, 2012 at 4:53 PM, Lawrence Crowl wrote: >>> On 10/30/12, Diego Novillo wrote: >>>> >>>> So, to use these three functions, the user must define this single >>>> 'is_a_helper' routine? Nothing else? >>> >>> You need to distinguish which kind user. Someone just wanting >>> to convert does not need to know about the is_a_helper stuff. >>> Someone wanting to extend the set of type relationships needs to >>> provide one or two template specializations. I've modified the >>> in-header documentation to better reflect the distinction. >> >> Great. >> >>> I originally had >>> >>> if (cgraph_node *ce = dyn_cast (e)) >>> if (!DECL_BUILT_IN (e->symbol.decl)) >>> lto_cgraph_replace_node (ce, cgraph (prevailing)); >>> >>> but folks objected to increasing the nesting, and asked that I >>> change to the pre-declare form. >> >> Ah, yeah. I remember that. OK, so we can now use both forms, right? > > Yes. > > I will commit the patch as soon as the merge and test is complete. Committed as follows. 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. } @@ -1128,7 +1128,7 @@ lsei_start_function_in_partition (lto_sy if (lsei_end_p (lsei)) return lsei; - if (!symtab_function_p (lsei_node (lsei)) + if (!is_a (lsei_node (lsei)) || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei))) lsei_next_function_in_partition (&lsei); @@ -1141,7 +1141,7 @@ lsei_next_variable_in_partition (lto_sym { lsei_next (lsei); while (!lsei_end_p (*lsei) - && (!symtab_variable_p (lsei_node (*lsei)) + && (!is_a (lsei_node (*lsei)) || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node (*lsei)))) lsei_next (lsei); } @@ -1154,7 +1154,7 @@ lsei_start_variable_in_partition (lto_sy if (lsei_end_p (lsei)) return lsei; - if (!symtab_variable_p (lsei_node (lsei)) + if (!is_a (lsei_node (lsei)) || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei))) lsei_next_variable_in_partition (&lsei); 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. Index: gcc/is-a.h =================================================================== --- gcc/is-a.h (revision 0) +++ gcc/is-a.h (revision 0) @@ -0,0 +1,201 @@ +/* Dynamic testing for abstract is-a relationships. + Copyright (C) 2012 Free Software Foundation, Inc. + Contributed by Lawrence Crowl. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + + +/* This header generic type query and conversion functions. + + +USING THE GENERIC TYPE FACILITY + + +The user functions are: + +bool is_a (pointer) + + Tests whether the pointer actually points to a more derived TYPE. + + Suppose you have a symtab_node_def *ptr, AKA symtab_node ptr. You can test + whether it points to a 'derived' cgraph_node as follows. + + if (is_a (ptr)) + .... + + +TYPE *as_a (pointer) + + Converts pointer to a TYPE*. + + You can just assume that it is such a node. + + do_something_with (as_a *ptr); + +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. + + This functions reduce compile time and increase type safety when treating a + generic item as a more specific item. + + You can test and obtain a pointer to the 'derived' type in one indivisible + operation. + + if (cgraph_node *cptr = dyn_cast (ptr)) + .... + + As an example, 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 approach + 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. + + +If you use these functions and get a 'inline function not defined' or a +'missing symbol' error message for 'is_a_helper<....>::test', it means that +the connection between the types has not been made. See below. + + +EXTENDING THE GENERIC TYPE FACILITY + +Each connection between types must be made by defining a specialization of the +template member function 'test' of the template class 'is_a_helper'. For +example, + + template <> + template <> + inline bool + is_a_helper ::test (symtab_node_def *p) + { + return p->symbol.type == SYMTAB_FUNCTION; + } + +If a simple reinterpret_cast between the pointer types is incorrect, then you +must also specialize the template member function 'cast'. Failure to do so +when needed may result in a crash. For example, + + template <> + template <> + inline bool + is_a_helper ::cast (symtab_node_def *p) + { + return &p->x_function; + } + +*/ + +#ifndef GCC_IS_A_H +#define GCC_IS_A_H + +/* A generic type conversion internal helper class. */ + +template +struct is_a_helper +{ + template + static inline bool test (U *p); + template + static inline T *cast (U *p); +}; + +/* Note that we deliberately do not define the 'test' member template. Not + doing so will result in a build-time error for type relationships that have + not been defined, rather than a run-time error. See the discussion above + for when to define this member. */ + +/* This is the generic implementation for casting from one type to another. + Do not use this routine directly; it is an internal function. See the + discussion above for when to define this member. */ + +template +template +inline T * +is_a_helper ::cast (U *p) +{ + return reinterpret_cast (p); +} + + +/* The public interface. */ + +/* A generic test for a type relationship. See the discussion above for when + to use this function. The question answered is "Is type T a derived type of + type U?". */ + +template +inline bool +is_a (U *p) +{ + return is_a_helper::test (p); +} + +/* A generic conversion from a base type U to a derived type T. See the + discussion above for when to use this function. */ + +template +inline T * +as_a (U *p) +{ + gcc_assert (is_a (p)); + return is_a_helper ::cast (p); +} + +/* A generic checked conversion from a base type U to a derived type T. See + the discussion above for when to use this function. */ + +template +inline T * +dyn_cast (U *p) +{ + if (is_a (p)) + return is_a_helper ::cast (p); + else + return static_cast (0); +} + +#endif /* GCC_IS_A_H */ Index: gcc/lto-symtab.c =================================================================== --- gcc/lto-symtab.c (revision 193006) +++ gcc/lto-symtab.c (working copy) @@ -532,11 +532,11 @@ lto_symtab_merge_cgraph_nodes_1 (symtab_ if (!symtab_real_symbol_p (e)) continue; - if (symtab_function_p (e) - && !DECL_BUILT_IN (e->symbol.decl)) - lto_cgraph_replace_node (cgraph (e), cgraph (prevailing)); - if (symtab_variable_p (e)) - lto_varpool_replace_node (varpool (e), varpool (prevailing)); + cgraph_node *ce = dyn_cast (e); + if (ce && !DECL_BUILT_IN (e->symbol.decl)) + lto_cgraph_replace_node (ce, cgraph (prevailing)); + if (varpool_node *ve = dyn_cast (e)) + lto_varpool_replace_node (ve, varpool (prevailing)); } return; Index: gcc/cgraphbuild.c =================================================================== --- gcc/cgraphbuild.c (revision 193006) +++ gcc/cgraphbuild.c (working copy) @@ -84,7 +84,7 @@ record_reference (tree *tp, int *walk_su if (TREE_CODE (decl) == VAR_DECL) { - struct varpool_node *vnode = varpool_node (decl); + struct varpool_node *vnode = varpool_node_for_decl (decl); ipa_record_reference ((symtab_node)ctx->varpool_node, (symtab_node)vnode, IPA_REF_ADDR, NULL); @@ -123,7 +123,7 @@ record_type_list (struct cgraph_node *no type = TREE_OPERAND (type, 0); if (TREE_CODE (type) == VAR_DECL) { - struct varpool_node *vnode = varpool_node (type); + struct varpool_node *vnode = varpool_node_for_decl (type); ipa_record_reference ((symtab_node)node, (symtab_node)vnode, IPA_REF_ADDR, NULL); @@ -233,7 +233,7 @@ mark_address (gimple stmt, tree addr, vo else if (addr && TREE_CODE (addr) == VAR_DECL && (TREE_STATIC (addr) || DECL_EXTERNAL (addr))) { - struct varpool_node *vnode = varpool_node (addr); + struct varpool_node *vnode = varpool_node_for_decl (addr); ipa_record_reference ((symtab_node)data, (symtab_node)vnode, @@ -262,7 +262,7 @@ mark_load (gimple stmt, tree t, void *da else if (t && TREE_CODE (t) == VAR_DECL && (TREE_STATIC (t) || DECL_EXTERNAL (t))) { - struct varpool_node *vnode = varpool_node (t); + struct varpool_node *vnode = varpool_node_for_decl (t); ipa_record_reference ((symtab_node)data, (symtab_node)vnode, @@ -280,7 +280,7 @@ mark_store (gimple stmt, tree t, void *d if (t && TREE_CODE (t) == VAR_DECL && (TREE_STATIC (t) || DECL_EXTERNAL (t))) { - struct varpool_node *vnode = varpool_node (t); + struct varpool_node *vnode = varpool_node_for_decl (t); ipa_record_reference ((symtab_node)data, (symtab_node)vnode, @@ -392,7 +392,7 @@ void record_references_in_initializer (tree decl, bool only_vars) { struct pointer_set_t *visited_nodes = pointer_set_create (); - struct varpool_node *node = varpool_node (decl); + struct varpool_node *node = varpool_node_for_decl (decl); struct record_reference_ctx ctx = {false, NULL}; ctx.varpool_node = node; Index: gcc/cgraph.c =================================================================== --- gcc/cgraph.c (revision 193006) +++ gcc/cgraph.c (working copy) @@ -503,12 +503,15 @@ cgraph_add_thunk (struct cgraph_node *de struct cgraph_node * cgraph_node_for_asm (tree asmname) { - symtab_node node = symtab_node_for_asm (asmname); - /* We do not want to look at inline clones. */ - for (node = symtab_node_for_asm (asmname); node; node = node->symbol.next_sharing_asm_name) - if (symtab_function_p (node) && !cgraph(node)->global.inlined_to) - return cgraph (node); + for (symtab_node node = symtab_node_for_asm (asmname); + node; + node = node->symbol.next_sharing_asm_name) + { + cgraph_node *cn = dyn_cast (node); + if (cn && !cn->global.inlined_to) + return cn; + } return NULL; } Index: gcc/cgraph.h =================================================================== --- gcc/cgraph.h (revision 193006) +++ gcc/cgraph.h (working copy) @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. #ifndef GCC_CGRAPH_H #define GCC_CGRAPH_H +#include "is-a.h" #include "plugin-api.h" #include "vec.h" #include "tree.h" @@ -457,12 +458,32 @@ struct GTY(()) asm_node { union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"), chain_prev ("%h.symbol.previous"))) symtab_node_def { struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol; - /* Use cgraph (symbol) accessor to get cgraph_node. */ + /* To access the following fields, + use the use dyn_cast or as_a to obtain the concrete type. */ struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function; - /* Use varpool (symbol) accessor to get varpool_node. */ struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable; }; +/* Report whether or not THIS symtab node is a function, aka cgraph_node. */ + +template <> +template <> +inline bool +is_a_helper ::test (symtab_node_def *p) +{ + return p->symbol.type == SYMTAB_FUNCTION; +} + +/* Report whether or not THIS symtab node is a vriable, aka varpool_node. */ + +template <> +template <> +inline bool +is_a_helper ::test (symtab_node_def *p) +{ + return p->symbol.type == SYMTAB_VARIABLE; +} + extern GTY(()) symtab_node symtab_nodes; extern GTY(()) int cgraph_n_nodes; extern GTY(()) int cgraph_max_uid; @@ -685,7 +706,7 @@ bool cgraph_maybe_hot_edge_p (struct cgr bool cgraph_optimize_for_size_p (struct cgraph_node *); /* In varpool.c */ -struct varpool_node *varpool_node (tree); +struct varpool_node *varpool_node_for_decl (tree); struct varpool_node *varpool_node_for_asm (tree asmname); void varpool_mark_needed_node (struct varpool_node *); void debug_varpool (void); @@ -715,19 +736,6 @@ void varpool_add_new_variable (tree); void symtab_initialize_asm_name_hash (void); void symtab_prevail_in_asm_name_hash (symtab_node node); -/* Return true when NODE is function. */ -static inline bool -symtab_function_p (symtab_node node) -{ - return node->symbol.type == SYMTAB_FUNCTION; -} - -/* Return true when NODE is variable. */ -static inline bool -symtab_variable_p (symtab_node node) -{ - return node->symbol.type == SYMTAB_VARIABLE; -} /* Return callgraph node for given symbol and check it is a function. */ static inline struct cgraph_node * @@ -800,10 +808,8 @@ varpool_first_variable (void) { symtab_node node; for (node = symtab_nodes; node; node = node->symbol.next) - { - if (symtab_variable_p (node)) - return varpool (node); - } + if (varpool_node *vnode = dyn_cast (node)) + return vnode; return NULL; } @@ -813,10 +819,8 @@ varpool_next_variable (struct varpool_no { symtab_node node1 = (symtab_node) node->symbol.next; for (; node1; node1 = node1->symbol.next) - { - if (symtab_variable_p (node1)) - return varpool (node1); - } + if (varpool_node *vnode1 = dyn_cast (node1)) + return vnode1; return NULL; } /* Walk all variables. */ @@ -832,9 +836,9 @@ varpool_first_static_initializer (void) symtab_node node; for (node = symtab_nodes; node; node = node->symbol.next) { - if (symtab_variable_p (node) - && DECL_INITIAL (node->symbol.decl)) - return varpool (node); + varpool_node *vnode = dyn_cast (node); + if (vnode && DECL_INITIAL (node->symbol.decl)) + return vnode; } return NULL; } @@ -846,9 +850,9 @@ varpool_next_static_initializer (struct symtab_node node1 = (symtab_node) node->symbol.next; for (; node1; node1 = node1->symbol.next) { - if (symtab_variable_p (node1) - && DECL_INITIAL (node1->symbol.decl)) - return varpool (node1); + varpool_node *vnode1 = dyn_cast (node1); + if (vnode1 && DECL_INITIAL (node1->symbol.decl)) + return vnode1; } return NULL; } @@ -865,8 +869,9 @@ varpool_first_defined_variable (void) symtab_node node; for (node = symtab_nodes; node; node = node->symbol.next) { - if (symtab_variable_p (node) && varpool (node)->analyzed) - return varpool (node); + varpool_node *vnode = dyn_cast (node); + if (vnode && vnode->analyzed) + return vnode; } return NULL; } @@ -878,8 +883,9 @@ varpool_next_defined_variable (struct va symtab_node node1 = (symtab_node) node->symbol.next; for (; node1; node1 = node1->symbol.next) { - if (symtab_variable_p (node1) && varpool (node1)->analyzed) - return varpool (node1); + varpool_node *vnode1 = dyn_cast (node1); + if (vnode1 && vnode1->analyzed) + return vnode1; } return NULL; } @@ -895,8 +901,9 @@ cgraph_first_defined_function (void) symtab_node node; for (node = symtab_nodes; node; node = node->symbol.next) { - if (symtab_function_p (node) && cgraph (node)->analyzed) - return cgraph (node); + cgraph_node *cn = dyn_cast (node); + if (cn && cn->analyzed) + return cn; } return NULL; } @@ -908,8 +915,9 @@ cgraph_next_defined_function (struct cgr symtab_node node1 = (symtab_node) node->symbol.next; for (; node1; node1 = node1->symbol.next) { - if (symtab_function_p (node1) && cgraph (node1)->analyzed) - return cgraph (node1); + cgraph_node *cn1 = dyn_cast (node1); + if (cn1 && cn1->analyzed) + return cn1; } return NULL; } @@ -925,10 +933,8 @@ cgraph_first_function (void) { symtab_node node; for (node = symtab_nodes; node; node = node->symbol.next) - { - if (symtab_function_p (node)) - return cgraph (node); - } + if (cgraph_node *cn = dyn_cast (node)) + return cn; return NULL; } @@ -938,10 +944,8 @@ cgraph_next_function (struct cgraph_node { symtab_node node1 = (symtab_node) node->symbol.next; for (; node1; node1 = node1->symbol.next) - { - if (symtab_function_p (node1)) - return cgraph (node1); - } + if (cgraph_node *cn1 = dyn_cast (node1)) + return cn1; return NULL; } /* Walk all functions. */ @@ -968,9 +972,9 @@ cgraph_first_function_with_gimple_body ( symtab_node node; for (node = symtab_nodes; node; node = node->symbol.next) { - if (symtab_function_p (node) - && cgraph_function_with_gimple_body_p (cgraph (node))) - return cgraph (node); + cgraph_node *cn = dyn_cast (node); + if (cn && cgraph_function_with_gimple_body_p (cn)) + return cn; } return NULL; } @@ -982,9 +986,9 @@ cgraph_next_function_with_gimple_body (s symtab_node node1 = node->symbol.next; for (; node1; node1 = node1->symbol.next) { - if (symtab_function_p (node1) - && cgraph_function_with_gimple_body_p (cgraph (node1))) - return cgraph (node1); + cgraph_node *cn1 = dyn_cast (node1); + if (cn1 && cgraph_function_with_gimple_body_p (cn1)) + return cn1; } return NULL; } @@ -1183,7 +1187,7 @@ cgraph_alias_aliased_node (struct cgraph ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref); gcc_checking_assert (ref->use == IPA_REF_ALIAS); - if (symtab_function_p (ref->referred)) + if (is_a (ref->referred)) return ipa_ref_node (ref); return NULL; } @@ -1197,7 +1201,7 @@ varpool_alias_aliased_node (struct varpo ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref); gcc_checking_assert (ref->use == IPA_REF_ALIAS); - if (symtab_variable_p (ref->referred)) + if (is_a (ref->referred)) return ipa_ref_varpool_node (ref); return NULL; } @@ -1328,7 +1332,7 @@ symtab_real_symbol_p (symtab_node node) struct cgraph_node *cnode; struct ipa_ref *ref; - if (!symtab_function_p (node)) + if (!is_a (node)) return true; cnode = cgraph (node); if (cnode->global.inlined_to) Index: gcc/tree-emutls.c =================================================================== --- gcc/tree-emutls.c (revision 193006) +++ gcc/tree-emutls.c (working copy) @@ -260,7 +260,7 @@ get_emutls_init_templ_addr (tree decl) /* Create varpool node for the new variable and finalize it if it is not external one. */ if (DECL_EXTERNAL (to)) - varpool_node (to); + varpool_node_for_decl (to); else varpool_add_new_variable (to); return build_fold_addr_expr (to); @@ -332,7 +332,7 @@ new_emutls_decl (tree decl, tree alias_o /* Create varpool node for the new variable and finalize it if it is not external one. */ if (DECL_EXTERNAL (to)) - varpool_node (to); + varpool_node_for_decl (to); else if (!alias_of) varpool_add_new_variable (to); else Index: gcc/ipa-reference.c =================================================================== --- gcc/ipa-reference.c (revision 193006) +++ gcc/ipa-reference.c (working copy) @@ -482,7 +482,7 @@ analyze_function (struct cgraph_node *fn local = init_function_info (fn); for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list, i, ref); i++) { - if (!symtab_variable_p (ref->referred)) + if (!is_a (ref->referred)) continue; var = ipa_ref_varpool_node (ref)->symbol.decl; if (!is_proper_for_analysis (var)) @@ -979,8 +979,6 @@ stream_out_bitmap (struct lto_simple_out static void ipa_reference_write_optimization_summary (void) { - struct cgraph_node *node; - symtab_node snode; struct lto_simple_output_block *ob = lto_create_simple_output_block (LTO_section_ipa_reference); unsigned int count = 0; @@ -994,12 +992,10 @@ ipa_reference_write_optimization_summary /* See what variables we are interested in. */ for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - struct varpool_node *vnode; - snode = lto_symtab_encoder_deref (encoder, i); - if (!symtab_variable_p (snode)) - continue; - vnode = varpool (snode); - if (bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl)) + symtab_node snode = lto_symtab_encoder_deref (encoder, i); + varpool_node *vnode = dyn_cast (snode); + if (vnode + && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl)) && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder)) { tree decl = vnode->symbol.decl; @@ -1013,10 +1009,12 @@ ipa_reference_write_optimization_summary if (ltrans_statics_bitcount) for (i = 0; i < lto_symtab_encoder_size (encoder); i++) - if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder, i)) - && write_node_summary_p (cgraph (snode), - encoder, ltrans_statics)) + { + symtab_node snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast (snode); + if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics)) count++; + } streamer_write_uhwi_stream (ob->main_stream, count); if (count) @@ -1027,17 +1025,15 @@ ipa_reference_write_optimization_summary if (ltrans_statics_bitcount) for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - snode = lto_symtab_encoder_deref (encoder, i); - if (!symtab_function_p (snode)) - continue; - node = cgraph (snode); - if (write_node_summary_p (node, encoder, ltrans_statics)) + symtab_node snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast (snode); + if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics)) { ipa_reference_optimization_summary_t info; int node_ref; - info = get_reference_optimization_summary (node); - node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node); + info = get_reference_optimization_summary (cnode); + node_ref = lto_symtab_encoder_encode (encoder, snode); streamer_write_uhwi_stream (ob->main_stream, node_ref); stream_out_bitmap (ob, info->statics_not_read, ltrans_statics, Index: gcc/cgraphunit.c =================================================================== --- gcc/cgraphunit.c (revision 193006) +++ gcc/cgraphunit.c (working copy) @@ -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 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); Index: gcc/cp/decl2.c =================================================================== --- gcc/cp/decl2.c (revision 193006) +++ gcc/cp/decl2.c (working copy) @@ -1775,7 +1775,7 @@ import_export_class (tree ctype) static bool var_finalized_p (tree var) { - return varpool_node (var)->finalized; + return varpool_node_for_decl (var)->finalized; } /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason, @@ -1893,7 +1893,7 @@ maybe_emit_vtables (tree ctype) TREE_ASM_WRITTEN (vtbl) = 1; else if (DECL_ONE_ONLY (vtbl)) { - current = varpool_node (vtbl); + current = varpool_node_for_decl (vtbl); if (last) symtab_add_to_same_comdat_group ((symtab_node) current, (symtab_node) last); last = current; Index: gcc/ipa-ref.c =================================================================== --- gcc/ipa-ref.c (revision 193006) +++ gcc/ipa-ref.c (working copy) @@ -42,7 +42,7 @@ ipa_record_reference (symtab_node referr struct ipa_ref_list *list, *list2; VEC(ipa_ref_t,gc) *old_references; - gcc_checking_assert (!stmt || symtab_function_p (referring_node)); + gcc_checking_assert (!stmt || is_a (referring_node)); gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt); list = &referring_node->symbol.ref_list; Index: gcc/lto-cgraph.c =================================================================== --- gcc/lto-cgraph.c (revision 193006) +++ gcc/lto-cgraph.c (working copy) @@ -679,7 +679,7 @@ add_references (lto_symtab_encoder_t enc int i; struct ipa_ref *ref; for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) - if (symtab_function_p (ref->referred)) + if (is_a (ref->referred)) add_node_to (encoder, ipa_ref_node (ref), false); else lto_symtab_encoder_encode (encoder, ref->referred); @@ -730,9 +730,8 @@ compute_ltrans_boundary (lto_symtab_enco for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { symtab_node node = lto_symtab_encoder_deref (encoder, i); - if (symtab_variable_p (node)) + if (varpool_node *vnode = dyn_cast (node)) { - struct varpool_node *vnode = varpool (node); if (DECL_INITIAL (vnode->symbol.decl) && !lto_symtab_encoder_encode_initializer_p (encoder, vnode) @@ -796,8 +795,8 @@ output_symtab (void) for (i = 0; i < n_nodes; i++) { symtab_node node = lto_symtab_encoder_deref (encoder, i); - if (symtab_function_p (node)) - lto_output_node (ob, cgraph (node), encoder); + if (cgraph_node *cnode = dyn_cast (node)) + lto_output_node (ob, cnode, encoder); else lto_output_varpool_node (ob, varpool (node), encoder); @@ -983,7 +982,7 @@ input_varpool_node (struct lto_file_decl order = streamer_read_hwi (ib) + order_base; decl_index = streamer_read_uhwi (ib); var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index); - node = varpool_node (var_decl); + node = varpool_node_for_decl (var_decl); node->symbol.order = order; if (order >= symtab_order) symtab_order = order + 1; @@ -1144,14 +1143,14 @@ input_cgraph_1 (struct lto_file_decl_dat /* AUX pointers should be all non-zero for function nodes read from the stream. */ #ifdef ENABLE_CHECKING FOR_EACH_VEC_ELT (symtab_node, nodes, i, node) - gcc_assert (node->symbol.aux || !symtab_function_p (node)); + gcc_assert (node->symbol.aux || !is_a (node)); #endif FOR_EACH_VEC_ELT (symtab_node, nodes, i, node) { int ref; - if (symtab_function_p (node)) + if (cgraph_node *cnode = dyn_cast (node)) { - ref = (int) (intptr_t) cgraph (node)->global.inlined_to; + ref = (int) (intptr_t) cnode->global.inlined_to; /* We share declaration of builtins, so we may read same node twice. */ if (!node->symbol.aux) @@ -1160,9 +1159,9 @@ input_cgraph_1 (struct lto_file_decl_dat /* Fixup inlined_to from reference to pointer. */ if (ref != LCC_NOT_FOUND) - cgraph (node)->global.inlined_to = cgraph (VEC_index (symtab_node, nodes, ref)); + cnode->global.inlined_to = cgraph (VEC_index (symtab_node, nodes, ref)); else - cgraph (node)->global.inlined_to = NULL; + cnode->global.inlined_to = NULL; } ref = (int) (intptr_t) node->symbol.same_comdat_group; @@ -1174,7 +1173,7 @@ input_cgraph_1 (struct lto_file_decl_dat node->symbol.same_comdat_group = NULL; } FOR_EACH_VEC_ELT (symtab_node, nodes, i, node) - node->symbol.aux = symtab_function_p (node) ? (void *)1 : NULL; + node->symbol.aux = is_a (node) ? (void *)1 : NULL; return nodes; } @@ -1449,7 +1448,6 @@ output_node_opt_summary (struct output_b static void output_cgraph_opt_summary (void) { - symtab_node node; int i, n_nodes; lto_symtab_encoder_t encoder; struct output_block *ob = create_output_block (LTO_section_cgraph_opt_sum); @@ -1459,18 +1457,21 @@ output_cgraph_opt_summary (void) encoder = ob->decl_state->symtab_node_encoder; n_nodes = lto_symtab_encoder_size (encoder); for (i = 0; i < n_nodes; i++) - if (symtab_function_p (node = lto_symtab_encoder_deref (encoder, i)) - && output_cgraph_opt_summary_p (cgraph (node))) - count++; + { + symtab_node node = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast (node); + if (cnode && output_cgraph_opt_summary_p (cnode)) + count++; + } streamer_write_uhwi (ob, count); for (i = 0; i < n_nodes; i++) { - node = lto_symtab_encoder_deref (encoder, i); - if (symtab_function_p (node) - && output_cgraph_opt_summary_p (cgraph (node))) + symtab_node node = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast (node); + if (cnode && output_cgraph_opt_summary_p (cnode)) { streamer_write_uhwi (ob, i); - output_node_opt_summary (ob, cgraph (node), encoder); + output_node_opt_summary (ob, cnode, encoder); } } produce_asm (ob, NULL); Index: gcc/lto-streamer-out.c =================================================================== --- gcc/lto-streamer-out.c (revision 193006) +++ gcc/lto-streamer-out.c (working copy) @@ -956,7 +956,6 @@ copy_function (struct cgraph_node *node) static void lto_output (void) { - struct cgraph_node *node; struct lto_out_decl_state *decl_state; #ifdef ENABLE_CHECKING bitmap output = lto_bitmap_alloc (); @@ -972,10 +971,9 @@ lto_output (void) for (i = 0; i < n_nodes; i++) { symtab_node snode = lto_symtab_encoder_deref (encoder, i); - if (!symtab_function_p (snode)) - continue; - node = cgraph (snode); - if (lto_symtab_encoder_encode_body_p (encoder, node) + cgraph_node *node = dyn_cast (snode); + if (node + && lto_symtab_encoder_encode_body_p (encoder, node) && !node->alias && !node->thunk.thunk_p) { Index: gcc/ada/gcc-interface/utils.c =================================================================== --- gcc/ada/gcc-interface/utils.c (revision 193006) +++ gcc/ada/gcc-interface/utils.c (working copy) @@ -5586,7 +5586,7 @@ gnat_write_global_declarations (void) void_type_node); TREE_STATIC (dummy_global) = 1; TREE_ASM_WRITTEN (dummy_global) = 1; - node = varpool_node (dummy_global); + node = varpool_node_for_decl (dummy_global); node->symbol.force_output = 1; while (!VEC_empty (tree, types_used_by_cur_var_decl)) Index: gcc/ipa.c =================================================================== --- gcc/ipa.c (revision 193006) +++ gcc/ipa.c (working copy) @@ -84,7 +84,7 @@ process_references (struct ipa_ref_list struct ipa_ref *ref; for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) { - if (symtab_function_p (ref->referred)) + if (is_a (ref->referred)) { struct cgraph_node *node = ipa_ref_node (ref); @@ -290,10 +290,8 @@ symtab_remove_unreachable_nodes (bool be before_inlining_p, reachable); } - if (symtab_function_p (node)) + if (cgraph_node *cnode = dyn_cast (node)) { - struct cgraph_node *cnode = cgraph (node); - /* Mark the callees reachable unless they are direct calls to extern inline functions we decided to not inline. */ if (!in_boundary_p) @@ -332,18 +330,18 @@ symtab_remove_unreachable_nodes (bool be } } /* When we see constructor of external variable, keep referred nodes in the - boundary. This will also hold initializers of the external vars NODE - reffers to. */ - if (symtab_variable_p (node) + boundary. This will also hold initializers of the external vars NODE + refers to. */ + varpool_node *vnode = dyn_cast (node); + if (vnode && DECL_EXTERNAL (node->symbol.decl) - && !varpool (node)->alias + && !vnode->alias && in_boundary_p) - { - int i; + { struct ipa_ref *ref; - for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) + for (int i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) enqueue_node (ref->referred, &first, reachable); - } + } } /* Remove unreachable functions. */ @@ -526,7 +524,7 @@ cgraph_address_taken_from_non_vtable_p ( if (ref->use == IPA_REF_ADDR) { struct varpool_node *node; - if (symtab_function_p (ref->referring)) + if (is_a (ref->referring)) return true; node = ipa_ref_referring_varpool_node (ref); if (!DECL_VIRTUAL_P (node->symbol.decl)) Index: gcc/ipa-inline-analysis.c =================================================================== --- gcc/ipa-inline-analysis.c (revision 193006) +++ gcc/ipa-inline-analysis.c (working copy) @@ -3855,22 +3855,25 @@ void inline_write_summary (void) { struct cgraph_node *node; - symtab_node snode; struct output_block *ob = create_output_block (LTO_section_inline_summary); lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder; unsigned int count = 0; int i; for (i = 0; i < lto_symtab_encoder_size (encoder); i++) - if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder, i)) - && cgraph (snode)->analyzed) - count++; + { + symtab_node snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast (snode); + if (cnode && cnode->analyzed) + count++; + } streamer_write_uhwi (ob, count); for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - if (symtab_function_p (snode = lto_symtab_encoder_deref (encoder, i)) - && (node = cgraph (snode))->analyzed) + symtab_node snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast (snode); + if (cnode && (node = cnode)->analyzed) { struct inline_summary *info = inline_summary (node); struct bitpack_d bp; @@ -3878,7 +3881,7 @@ inline_write_summary (void) int i; size_time_entry *e; struct condition *c; - + streamer_write_uhwi (ob, lto_symtab_encoder_encode (encoder, (symtab_node)node)); streamer_write_hwi (ob, info->estimated_self_stack_size); streamer_write_hwi (ob, info->self_size); @@ -3897,7 +3900,7 @@ inline_write_summary (void) bp_pack_value (&bp, c->by_ref, 1); streamer_write_bitpack (&bp); if (c->agg_contents) - streamer_write_uhwi (ob, c->offset); + streamer_write_uhwi (ob, c->offset); } streamer_write_uhwi (ob, VEC_length (size_time_entry, info->entry)); for (i = 0; Index: gcc/lto/lto.c =================================================================== --- gcc/lto/lto.c (revision 193006) +++ gcc/lto/lto.c (working copy) @@ -2671,12 +2671,17 @@ lto_wpa_write_files (void) if (!lto_symtab_encoder_in_partition_p (part->encoder, node)) { fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name (node)); - if (symtab_function_p (node) - && lto_symtab_encoder_encode_body_p (part->encoder, cgraph (node))) + cgraph_node *cnode = dyn_cast (node); + if (cnode + && lto_symtab_encoder_encode_body_p (part->encoder, cnode)) fprintf (cgraph_dump_file, "(body included)"); - else if (symtab_variable_p (node) - && lto_symtab_encoder_encode_initializer_p (part->encoder, varpool (node))) - fprintf (cgraph_dump_file, "(initializer included)"); + else + { + varpool_node *vnode = dyn_cast (node); + if (vnode + && lto_symtab_encoder_encode_initializer_p (part->encoder, vnode)) + fprintf (cgraph_dump_file, "(initializer included)"); + } } } fprintf (cgraph_dump_file, "\n"); Index: gcc/lto/lto-partition.c =================================================================== --- gcc/lto/lto-partition.c (revision 193006) +++ gcc/lto/lto-partition.c (working copy) @@ -55,22 +55,22 @@ get_symbol_class (symtab_node node) { /* Inline clones are always duplicated. This include external delcarations. */ - if (symtab_function_p (node) - && cgraph (node)->global.inlined_to) + cgraph_node *cnode = dyn_cast (node); + if (cnode && cnode->global.inlined_to) return SYMBOL_DUPLICATE; /* External declarations are external. */ if (DECL_EXTERNAL (node->symbol.decl)) return SYMBOL_EXTERNAL; - if (symtab_variable_p (node)) + if (varpool_node *vnode = dyn_cast (node)) { /* Constant pool references use local symbol names that can not be promoted global. We should never put into a constant pool objects that can not be duplicated across partitions. */ if (DECL_IN_CONSTANT_POOL (node->symbol.decl)) return SYMBOL_DUPLICATE; - gcc_checking_assert (varpool (node)->analyzed); + gcc_checking_assert (vnode->analyzed); } /* Functions that are cloned may stay in callgraph even if they are unused. Handle them as external; compute_ltrans_boundary take care to make @@ -145,7 +145,7 @@ add_references_to_partition (ltrans_part /* References to a readonly variable may be constant foled into its value. Recursively look into the initializers of the constant variable and add references, too. */ - else if (symtab_variable_p (ref->referred) + else if (is_a (ref->referred) && const_value_known_p (ref->referred->symbol.decl) && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred)) { @@ -196,9 +196,8 @@ add_symbol_to_partition_1 (ltrans_partit } node->symbol.aux = (void *)((size_t)node->symbol.aux + 1); - if (symtab_function_p (node)) + if (cgraph_node *cnode = dyn_cast (node)) { - struct cgraph_node *cnode = cgraph (node); struct cgraph_edge *e; part->insns += inline_summary (cnode)->self_size; @@ -247,15 +246,15 @@ contained_in_symbol (symtab_node node) if (lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl))) return node; - if (symtab_function_p (node)) + if (cgraph_node *cnode = dyn_cast (node)) { - struct cgraph_node *cnode = cgraph_function_node (cgraph (node), NULL); + cnode = cgraph_function_node (cnode, NULL); if (cnode->global.inlined_to) cnode = cnode->global.inlined_to; return (symtab_node) cnode; } - else if (symtab_variable_p (node)) - return (symtab_node) varpool_variable_node (varpool (node), NULL); + else if (varpool_node *vnode = dyn_cast (node)) + return (symtab_node) varpool_variable_node (vnode, NULL); return node; } @@ -302,8 +301,8 @@ undo_partition (ltrans_partition partiti pointer_set_destroy (partition->initializers_visited); partition->initializers_visited = NULL; - if (symtab_function_p (node)) - partition->insns -= inline_summary (cgraph (node))->self_size; + if (cgraph_node *cnode = dyn_cast (node)) + partition->insns -= inline_summary (cnode)->self_size; lto_symtab_encoder_delete_node (partition->encoder, node); node->symbol.aux = (void *)((size_t)node->symbol.aux - 1); } @@ -555,11 +554,10 @@ lto_balanced_map (void) symtab_node snode = lto_symtab_encoder_deref (partition->encoder, last_visited_node); - if (symtab_function_p (snode)) + if (cgraph_node *node = dyn_cast (snode)) { struct cgraph_edge *edge; - node = cgraph (snode); refs = &node->symbol.ref_list; last_visited_node++; @@ -611,7 +609,7 @@ lto_balanced_map (void) /* Compute boundary cost of IPA REF edges and at the same time look into variables referenced from current partition and try to add them. */ for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++) - if (symtab_variable_p (ref->referred)) + if (is_a (ref->referred)) { int index; @@ -645,7 +643,7 @@ lto_balanced_map (void) cost++; } for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++) - if (symtab_variable_p (ref->referring)) + if (is_a (ref->referring)) { int index; Index: gcc/varasm.c =================================================================== --- gcc/varasm.c (revision 193006) +++ gcc/varasm.c (working copy) @@ -2221,7 +2221,7 @@ mark_decl_referenced (tree decl) } else if (TREE_CODE (decl) == VAR_DECL) { - struct varpool_node *node = varpool_node (decl); + struct varpool_node *node = varpool_node_for_decl (decl); /* C++ frontend use mark_decl_references to force COMDAT variables to be output that might appear dead otherwise. */ node->symbol.force_output = true; @@ -5549,7 +5549,7 @@ assemble_alias (tree decl, tree target) if (TREE_CODE (decl) == FUNCTION_DECL) cgraph_get_create_node (decl)->alias = true; else - varpool_node (decl)->alias = true; + varpool_node_for_decl (decl)->alias = true; /* If the target has already been emitted, we don't have to queue the alias. This saves a tad of memory. */ Index: gcc/symtab.c =================================================================== --- gcc/symtab.c (revision 193006) +++ gcc/symtab.c (working copy) @@ -104,7 +104,7 @@ eq_assembler_name (const void *p1, const static void insert_to_assembler_name_hash (symtab_node node) { - if (symtab_variable_p (node) && DECL_HARD_REGISTER (node->symbol.decl)) + if (is_a (node) && DECL_HARD_REGISTER (node->symbol.decl)) return; gcc_checking_assert (!node->symbol.previous_sharing_asm_name && !node->symbol.next_sharing_asm_name); @@ -252,8 +252,8 @@ symtab_unregister_node (symtab_node node if (*slot == node) { symtab_node replacement_node = NULL; - if (symtab_function_p (node)) - replacement_node = (symtab_node)cgraph_find_replacement_node (cgraph (node)); + if (cgraph_node *cnode = dyn_cast (node)) + replacement_node = (symtab_node)cgraph_find_replacement_node (cnode); if (!replacement_node) htab_clear_slot (symtab_hash, slot); else @@ -294,10 +294,10 @@ symtab_get_node (const_tree decl) void symtab_remove_node (symtab_node node) { - if (symtab_function_p (node)) - cgraph_remove_node (cgraph (node)); - else if (symtab_variable_p (node)) - varpool_remove_node (varpool (node)); + if (cgraph_node *cnode = dyn_cast (node)) + cgraph_remove_node (cnode); + else if (varpool_node *vnode = dyn_cast (node)) + varpool_remove_node (vnode); } /* Initalize asm name hash unless. */ @@ -538,10 +538,10 @@ dump_symtab_base (FILE *f, symtab_node n void dump_symtab_node (FILE *f, symtab_node node) { - if (symtab_function_p (node)) - dump_cgraph_node (f, cgraph (node)); - else if (symtab_variable_p (node)) - dump_varpool_node (f, varpool (node)); + if (cgraph_node *cnode = dyn_cast (node)) + dump_cgraph_node (f, cnode); + else if (varpool_node *vnode = dyn_cast (node)) + dump_varpool_node (f, vnode); } /* Dump symbol table. */ @@ -579,7 +579,7 @@ verify_symtab_base (symtab_node node) bool error_found = false; symtab_node hashed_node; - if (symtab_function_p (node)) + if (is_a (node)) { if (TREE_CODE (node->symbol.decl) != FUNCTION_DECL) { @@ -587,7 +587,7 @@ verify_symtab_base (symtab_node node) error_found = true; } } - else if (symtab_variable_p (node)) + else if (is_a (node)) { if (TREE_CODE (node->symbol.decl) != VAR_DECL) { @@ -622,7 +622,8 @@ verify_symtab_base (symtab_node node) hashed_node = hashed_node->symbol.next_sharing_asm_name; } if (!hashed_node - && !(symtab_variable_p (node) || DECL_HARD_REGISTER (node->symbol.decl))) + && !(is_a (node) + || DECL_HARD_REGISTER (node->symbol.decl))) { error ("node not found in symtab assembler name hash"); error_found = true; @@ -676,8 +677,8 @@ verify_symtab_node (symtab_node node) return; timevar_push (TV_CGRAPH_VERIFY); - if (symtab_function_p (node)) - verify_cgraph_node (cgraph (node)); + if (cgraph_node *cnode = dyn_cast (node)) + verify_cgraph_node (cnode); else if (verify_symtab_base (node)) { Index: gcc/Makefile.in =================================================================== --- gcc/Makefile.in (revision 193006) +++ gcc/Makefile.in (working copy) @@ -886,7 +886,7 @@ CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) v IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H) IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H) CGRAPH_H = cgraph.h $(VEC_H) $(TREE_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \ - cif-code.def ipa-ref.h ipa-ref-inline.h $(LINKER_PLUGIN_API_H) + cif-code.def ipa-ref.h ipa-ref-inline.h $(LINKER_PLUGIN_API_H) is-a.h DF_H = df.h $(BITMAP_H) $(REGSET_H) sbitmap.h $(BASIC_BLOCK_H) \ alloc-pool.h $(TIMEVAR_H) VALTRACK_H = valtrack.h $(BITMAP_H) $(DF_H) $(RTL_H) $(BASIC_BLOCK_H) \ Index: gcc/passes.c =================================================================== --- gcc/passes.c (revision 193006) +++ gcc/passes.c (working copy) @@ -201,7 +201,7 @@ rest_of_decl_compilation (tree decl, ; else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl) && TREE_STATIC (decl)) - varpool_node (decl); + varpool_node_for_decl (decl); } /* Called after finishing a record, union or enumeral type. */ Index: gcc/varpool.c =================================================================== --- gcc/varpool.c (revision 193006) +++ gcc/varpool.c (working copy) @@ -39,7 +39,7 @@ along with GCC; see the file COPYING3. /* Return varpool node assigned to DECL. Create new one when needed. */ struct varpool_node * -varpool_node (tree decl) +varpool_node_for_decl (tree decl) { struct varpool_node *node = varpool_get_node (decl); gcc_assert (TREE_CODE (decl) == VAR_DECL @@ -114,9 +114,9 @@ debug_varpool (void) struct varpool_node * varpool_node_for_asm (tree asmname) { - symtab_node node = symtab_node_for_asm (asmname); - if (node && symtab_variable_p (node)) - return varpool (node); + if (symtab_node node = symtab_node_for_asm (asmname)) + if (varpool_node *vnode = dyn_cast (node)) + return vnode; return NULL; } @@ -192,7 +192,7 @@ varpool_add_new_variable (tree decl) { struct varpool_node *node; varpool_finalize_decl (decl); - node = varpool_node (decl); + node = varpool_node_for_decl (decl); if (varpool_externally_visible_p (node, false)) node->symbol.externally_visible = true; } @@ -232,7 +232,7 @@ varpool_analyze_node (struct varpool_nod } if (node->alias && node->alias_of) { - struct varpool_node *tgt = varpool_node (node->alias_of); + struct varpool_node *tgt = varpool_node_for_decl (node->alias_of); struct varpool_node *n; for (n = tgt; n && n->alias; @@ -378,16 +378,21 @@ varpool_remove_unreferenced_decls (void) for (next = node->symbol.same_comdat_group; next != (symtab_node)node; next = next->symbol.same_comdat_group) - if (symtab_variable_p (next) - && varpool (next)->analyzed) - enqueue_node (varpool (next), &first); + { + varpool_node *vnext = dyn_cast (next); + if (vnext && vnext->analyzed) + enqueue_node (vnext, &first); + } } for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) - if (symtab_variable_p (ref->referred) - && (!DECL_EXTERNAL (ref->referred->symbol.decl) - || varpool (ref->referred)->alias) - && varpool (ref->referred)->analyzed) - enqueue_node (varpool (ref->referred), &first); + { + varpool_node *vnode = dyn_cast (ref->referred); + if (vnode + && (!DECL_EXTERNAL (ref->referred->symbol.decl) + || vnode->alias) + && vnode->analyzed) + enqueue_node (vnode, &first); + } } if (cgraph_dump_file) fprintf (cgraph_dump_file, "\nRemoving variables:"); @@ -461,7 +466,7 @@ add_new_static_var (tree type) DECL_CONTEXT (new_decl) = NULL_TREE; DECL_ABSTRACT (new_decl) = 0; lang_hooks.dup_lang_specific_decl (new_decl); - new_node = varpool_node (new_decl); + new_node = varpool_node_for_decl (new_decl); varpool_finalize_decl (new_decl); return new_node->symbol.decl; @@ -477,7 +482,7 @@ varpool_create_variable_alias (tree alia gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (alias) == VAR_DECL); - alias_node = varpool_node (alias); + alias_node = varpool_node_for_decl (alias); alias_node->alias = 1; alias_node->finalized = 1; alias_node->alias_of = decl; Index: gcc/lto-streamer.h =================================================================== --- gcc/lto-streamer.h (revision 193006) +++ gcc/lto-streamer.h (working copy) @@ -1115,7 +1115,7 @@ lsei_next_function_in_partition (lto_sym { lsei_next (lsei); while (!lsei_end_p (*lsei) - && (!symtab_function_p (lsei_node (*lsei)) + && (!is_a (lsei_node (*lsei)) || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node (*lsei)))) lsei_next (lsei);