LCOV - code coverage report
Current view: top level - gcc - ipa-visibility.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 370 387 95.6 %
Date: 2020-04-04 11:58:09 Functions: 19 19 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* IPA visibility pass
       2                 :            :    Copyright (C) 2003-2020 Free Software Foundation, Inc.
       3                 :            : 
       4                 :            : This file is part of GCC.
       5                 :            : 
       6                 :            : GCC is free software; you can redistribute it and/or modify it under
       7                 :            : the terms of the GNU General Public License as published by the Free
       8                 :            : Software Foundation; either version 3, or (at your option) any later
       9                 :            : version.
      10                 :            : 
      11                 :            : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :            : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :            : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :            : for more details.
      15                 :            : 
      16                 :            : You should have received a copy of the GNU General Public License
      17                 :            : along with GCC; see the file COPYING3.  If not see
      18                 :            : <http://www.gnu.org/licenses/>.  */
      19                 :            : 
      20                 :            : /* This file implements two related passes: 
      21                 :            : 
      22                 :            :      - pass_data_ipa_function_and_variable_visibility run just after
      23                 :            :        symbol table, references and callgraph are built
      24                 :            : 
      25                 :            :      - pass_data_ipa_function_and_variable_visibility run as first
      26                 :            :        proper IPA pass (that is after early optimization, or, (with LTO)
      27                 :            :        as a first pass done at link-time.
      28                 :            : 
      29                 :            :    Purpose of both passes is to set correctly visibility properties
      30                 :            :    of all symbols.  This includes:
      31                 :            : 
      32                 :            :     - Symbol privatization:
      33                 :            : 
      34                 :            :       Some symbols that are declared public by frontend may be
      35                 :            :       turned local (either by -fwhole-program flag, by linker plugin feedback
      36                 :            :       or by other reasons)
      37                 :            : 
      38                 :            :     - Discovery of local functions:
      39                 :            : 
      40                 :            :       A local function is one whose calls can occur only in the current
      41                 :            :       compilation unit and all its calls are explicit, so we can change
      42                 :            :       its calling convention.  We simply mark all static functions whose
      43                 :            :       address is not taken as local.
      44                 :            : 
      45                 :            :       externally_visible flag is set for symbols that cannot be privatized.
      46                 :            :       For privatized symbols we clear TREE_PUBLIC flag and dismantle comdat
      47                 :            :       group.
      48                 :            : 
      49                 :            :     - Dismantling of comdat groups:
      50                 :            : 
      51                 :            :       Comdat group represent a section that may be replaced by linker by
      52                 :            :       a different copy of the same section from other unit.
      53                 :            :       If we have resolution information (from linker plugin) and we know that
      54                 :            :       a given comdat gorup is prevailing, we can dismantle it and turn symbols
      55                 :            :       into normal symbols.  If the resolution information says that the
      56                 :            :       section was previaled by copy from non-LTO code, we can also dismantle
      57                 :            :       it and turn all symbols into external.
      58                 :            : 
      59                 :            :     - Local aliases:
      60                 :            : 
      61                 :            :       Some symbols can be interposed by dynamic linker. Refering to these
      62                 :            :       symbols is expensive, since it needs to be overwritable by the dynamic
      63                 :            :       linker.  In some cases we know that the interposition does not change
      64                 :            :       semantic and we can always refer to a local copy (as in the case of
      65                 :            :       inline function).  In this case we produce a local alias and redirect
      66                 :            :       calls to it.
      67                 :            : 
      68                 :            :       TODO: This should be done for references, too.
      69                 :            : 
      70                 :            :     - Removal of static ocnstructors and destructors that have no side effects.
      71                 :            : 
      72                 :            :     - Regularization of several oddities introduced by frontends that may
      73                 :            :       be impractical later in the optimization queue.  */
      74                 :            : 
      75                 :            : #include "config.h"
      76                 :            : #include "system.h"
      77                 :            : #include "coretypes.h"
      78                 :            : #include "tm.h"
      79                 :            : #include "function.h"
      80                 :            : #include "tree.h"
      81                 :            : #include "gimple-expr.h"
      82                 :            : #include "tree-pass.h"
      83                 :            : #include "cgraph.h"
      84                 :            : #include "calls.h"
      85                 :            : #include "varasm.h"
      86                 :            : #include "ipa-utils.h"
      87                 :            : #include "stringpool.h"
      88                 :            : #include "attribs.h"
      89                 :            : 
      90                 :            : /* Return true when NODE cannot be local. Worker for cgraph_local_node_p.  */
      91                 :            : 
      92                 :            : static bool
      93                 :    3262540 : non_local_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
      94                 :            : {
      95                 :    3262540 :   return !(node->only_called_directly_or_aliased_p ()
      96                 :            :            /* i386 would need update to output thunk with local calling
      97                 :            :               conventions.  */
      98                 :     355132 :            && !node->thunk.thunk_p
      99                 :     355132 :            && node->definition
     100                 :     355100 :            && !DECL_EXTERNAL (node->decl)
     101                 :     189410 :            && !lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl))
     102                 :            :            && !node->externally_visible
     103                 :            :            && !node->used_from_other_partition
     104                 :     188970 :            && !node->in_other_partition
     105                 :     188970 :            && node->get_availability () >= AVAIL_AVAILABLE);
     106                 :            : }
     107                 :            : 
     108                 :            : /* Return true when function can be marked local.  */
     109                 :            : 
     110                 :            : bool
     111                 :    3230520 : cgraph_node::local_p (void)
     112                 :            : {
     113                 :    3237020 :    cgraph_node *n = ultimate_alias_target ();
     114                 :            : 
     115                 :    3237020 :    if (n->thunk.thunk_p)
     116                 :       6505 :      return n->callees->callee->local_p ();
     117                 :    3230520 :    return !n->call_for_symbol_thunks_and_aliases (non_local_p,
     118                 :    3230520 :                                                   NULL, true);
     119                 :            :                                         
     120                 :            : }
     121                 :            : 
     122                 :            : /* A helper for comdat_can_be_unshared_p.  */
     123                 :            : 
     124                 :            : static bool
     125                 :       1550 : comdat_can_be_unshared_p_1 (symtab_node *node)
     126                 :            : {
     127                 :       1550 :   if (!node->externally_visible)
     128                 :            :     return true;
     129                 :       1359 :   if (node->address_can_be_compared_p ())
     130                 :            :     {
     131                 :            :       struct ipa_ref *ref;
     132                 :            : 
     133                 :       1522 :       for (unsigned int i = 0; node->iterate_referring (i, ref); i++)
     134                 :        637 :         if (ref->address_matters_p ())
     135                 :       1550 :           return false;
     136                 :            :     }
     137                 :            : 
     138                 :            :   /* If the symbol is used in some weird way, better to not touch it.  */
     139                 :        893 :   if (node->force_output)
     140                 :            :     return false;
     141                 :            : 
     142                 :            :   /* Explicit instantiations needs to be output when possibly
     143                 :            :      used externally.  */
     144                 :        893 :   if (node->forced_by_abi
     145                 :        893 :       && TREE_PUBLIC (node->decl)
     146                 :         52 :       && (node->resolution != LDPR_PREVAILING_DEF_IRONLY
     147                 :         52 :           && !flag_whole_program))
     148                 :            :     return false;
     149                 :            : 
     150                 :            :   /* Non-readonly and volatile variables cannot be duplicated.  */
     151                 :        845 :   if (is_a <varpool_node *> (node)
     152                 :        211 :       && (!TREE_READONLY (node->decl)
     153                 :        208 :           || TREE_THIS_VOLATILE (node->decl)))
     154                 :          3 :     return false;
     155                 :            :   return true;
     156                 :            : }
     157                 :            : 
     158                 :            : /* COMDAT functions must be shared only if they have address taken,
     159                 :            :    otherwise we can produce our own private implementation with
     160                 :            :    -fwhole-program.  
     161                 :            :    Return true when turning COMDAT function static cannot lead to wrong
     162                 :            :    code when the resulting object links with a library defining same COMDAT.
     163                 :            : 
     164                 :            :    Virtual functions do have their addresses taken from the vtables,
     165                 :            :    but in C++ there is no way to compare their addresses for equality.  */
     166                 :            : 
     167                 :            : static bool
     168                 :       1176 : comdat_can_be_unshared_p (symtab_node *node)
     169                 :            : {
     170                 :       1176 :   if (!comdat_can_be_unshared_p_1 (node))
     171                 :            :     return false;
     172                 :        659 :   if (node->same_comdat_group)
     173                 :            :     {
     174                 :            :       symtab_node *next;
     175                 :            : 
     176                 :            :       /* If more than one function is in the same COMDAT group, it must
     177                 :            :          be shared even if just one function in the comdat group has
     178                 :            :          address taken.  */
     179                 :        374 :       for (next = node->same_comdat_group;
     180                 :        600 :            next != node; next = next->same_comdat_group)
     181                 :        374 :         if (!comdat_can_be_unshared_p_1 (next))
     182                 :            :           return false;
     183                 :            :     }
     184                 :            :   return true;
     185                 :            : }
     186                 :            : 
     187                 :            : /* Return true when function NODE should be considered externally visible.  */
     188                 :            : 
     189                 :            : static bool
     190                 :    6113410 : cgraph_externally_visible_p (struct cgraph_node *node,
     191                 :            :                              bool whole_program)
     192                 :            : {
     193                 :    6113500 :   while (node->transparent_alias && node->definition)
     194                 :    6113500 :     node = node->get_alias_target ();
     195                 :    6113410 :   if (!node->definition)
     196                 :            :     return false;
     197                 :    3298940 :   if (!TREE_PUBLIC (node->decl)
     198                 :    3298940 :       || DECL_EXTERNAL (node->decl))
     199                 :            :     return false;
     200                 :            : 
     201                 :            :   /* Do not try to localize built-in functions yet.  One of problems is that we
     202                 :            :      end up mangling their asm for WHOPR that makes it impossible to call them
     203                 :            :      using the implicit built-in declarations anymore.  Similarly this enables
     204                 :            :      us to remove them as unreachable before actual calls may appear during
     205                 :            :      expansion or folding.  */
     206                 :    2642500 :   if (fndecl_built_in_p (node->decl))
     207                 :            :     return true;
     208                 :            : 
     209                 :            :   /* If linker counts on us, we must preserve the function.  */
     210                 :    2632710 :   if (node->used_from_object_file_p ())
     211                 :            :     return true;
     212                 :    2627840 :   if (DECL_PRESERVE_P (node->decl))
     213                 :            :     return true;
     214                 :    2622480 :   if (lookup_attribute ("externally_visible",
     215                 :    2622480 :                         DECL_ATTRIBUTES (node->decl)))
     216                 :            :     return true;
     217                 :    2579660 :   if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)))
     218                 :            :     return true;
     219                 :            :   if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
     220                 :            :       && lookup_attribute ("dllexport",
     221                 :            :                            DECL_ATTRIBUTES (node->decl)))
     222                 :            :     return true;
     223                 :            : 
     224                 :            :   /* Limitation of gas requires us to output targets of symver aliases as
     225                 :            :      global symbols.  This is binutils PR 25295.  */
     226                 :            :   ipa_ref *ref;
     227                 :    3383060 :   FOR_EACH_ALIAS (node, ref)
     228                 :     273239 :     if (ref->referring->symver)
     229                 :            :       return true;
     230                 :            : 
     231                 :    2570790 :   if (node->resolution == LDPR_PREVAILING_DEF_IRONLY)
     232                 :            :     return false;
     233                 :            :   /* When doing LTO or whole program, we can bring COMDAT functions static.
     234                 :            :      This improves code quality and we know we will duplicate them at most twice
     235                 :            :      (in the case that we are not using plugin and link with object file
     236                 :            :       implementing same COMDAT)  */
     237                 :    2538660 :   if (((in_lto_p || whole_program) && !flag_incremental_link)
     238                 :      29609 :       && DECL_COMDAT (node->decl)
     239                 :    2539210 :       && comdat_can_be_unshared_p (node))
     240                 :            :     return false;
     241                 :            : 
     242                 :            :   /* When doing link time optimizations, hidden symbols become local.  */
     243                 :      29054 :   if ((in_lto_p && !flag_incremental_link)
     244                 :      28808 :       && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
     245                 :      28806 :           || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
     246                 :            :       /* Be sure that node is defined in IR file, not in other object
     247                 :            :          file.  In that case we don't set used_from_other_object_file.  */
     248                 :    2538110 :       && node->definition)
     249                 :            :     ;
     250                 :    2538110 :   else if (!whole_program)
     251                 :            :     return true;
     252                 :            : 
     253                 :        282 :   if (MAIN_NAME_P (DECL_NAME (node->decl)))
     254                 :        168 :     return true;
     255                 :            : 
     256                 :            :   return false;
     257                 :            : }
     258                 :            : 
     259                 :            : /* Return true when variable should be considered externally visible.  */
     260                 :            : 
     261                 :            : bool
     262                 :    4716820 : varpool_node::externally_visible_p (void)
     263                 :            : {
     264                 :    4716830 :   while (transparent_alias && definition)
     265                 :         20 :     return get_alias_target ()->externally_visible_p ();
     266                 :    4716820 :   if (DECL_EXTERNAL (decl))
     267                 :            :     return true;
     268                 :            : 
     269                 :    4699520 :   if (!TREE_PUBLIC (decl))
     270                 :            :     return false;
     271                 :            : 
     272                 :            :   /* If linker counts on us, we must preserve the function.  */
     273                 :    2373870 :   if (used_from_object_file_p ())
     274                 :            :     return true;
     275                 :            : 
     276                 :            :   /* Bringing TLS variables local may cause dynamic linker failures
     277                 :            :      on limits of static TLS vars.  */
     278                 :    2373850 :   if (DECL_THREAD_LOCAL_P (decl)
     279                 :    2378800 :       && (DECL_TLS_MODEL (decl) != TLS_MODEL_EMULATED
     280                 :       4952 :           && DECL_TLS_MODEL (decl) != TLS_MODEL_INITIAL_EXEC))
     281                 :            :     return true;
     282                 :            : 
     283                 :    2369030 :   if (DECL_HARD_REGISTER (decl))
     284                 :            :     return true;
     285                 :    2368940 :   if (DECL_PRESERVE_P (decl))
     286                 :            :     return true;
     287                 :    2368270 :   if (lookup_attribute ("externally_visible",
     288                 :    2368270 :                         DECL_ATTRIBUTES (decl)))
     289                 :            :     return true;
     290                 :            :   if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
     291                 :            :       && lookup_attribute ("dllexport",
     292                 :            :                            DECL_ATTRIBUTES (decl)))
     293                 :            :     return true;
     294                 :            : 
     295                 :            :   /* Limitation of gas requires us to output targets of symver aliases as
     296                 :            :      global symbols.  This is binutils PR 25295.  */
     297                 :            :   ipa_ref *ref;
     298                 :    2371020 :   FOR_EACH_ALIAS (this, ref)
     299                 :        193 :     if (ref->referring->symver)
     300                 :            :       return true;
     301                 :            : 
     302                 :    2368190 :   if (resolution == LDPR_PREVAILING_DEF_IRONLY)
     303                 :            :     return false;
     304                 :            : 
     305                 :            :   /* As a special case, the COMDAT virtual tables can be unshared.
     306                 :            :      In LTO mode turn vtables into static variables.  The variable is readonly,
     307                 :            :      so this does not enable more optimization, but referring static var
     308                 :            :      is faster for dynamic linking.  Also this match logic hidding vtables
     309                 :            :      from LTO symbol tables.  */
     310                 :    2360850 :   if (((in_lto_p || flag_whole_program) && !flag_incremental_link)
     311                 :       5355 :       && DECL_COMDAT (decl)
     312                 :    2361480 :       && comdat_can_be_unshared_p (this))
     313                 :            :     return false;
     314                 :            : 
     315                 :            :   /* When doing link time optimizations, hidden symbols become local.  */
     316                 :       5221 :   if (in_lto_p && !flag_incremental_link
     317                 :       5047 :       && (DECL_VISIBILITY (decl) == VISIBILITY_HIDDEN
     318                 :       5046 :           || DECL_VISIBILITY (decl) == VISIBILITY_INTERNAL)
     319                 :            :       /* Be sure that node is defined in IR file, not in other object
     320                 :            :          file.  In that case we don't set used_from_other_object_file.  */
     321                 :    2360740 :       && definition)
     322                 :            :     ;
     323                 :    2360740 :   else if (!flag_whole_program)
     324                 :            :     return true;
     325                 :            : 
     326                 :            :   /* Do not attempt to privatize COMDATS by default.
     327                 :            :      This would break linking with C++ libraries sharing
     328                 :            :      inline definitions.
     329                 :            : 
     330                 :            :      FIXME: We can do so for readonly vars with no address taken and
     331                 :            :      possibly also for vtables since no direct pointer comparsion is done.
     332                 :            :      It might be interesting to do so to reduce linking overhead.  */
     333                 :        227 :   if (DECL_COMDAT (decl) || DECL_WEAK (decl))
     334                 :          3 :     return true;
     335                 :            :   return false;
     336                 :            : }
     337                 :            : 
     338                 :            : /* Return true if reference to NODE can be replaced by a local alias.
     339                 :            :    Local aliases save dynamic linking overhead and enable more optimizations.
     340                 :            :  */
     341                 :            : 
     342                 :            : static bool
     343                 :    2052530 : can_replace_by_local_alias (symtab_node *node)
     344                 :            : {
     345                 :            :   /* If aliases aren't supported, we can't do replacement.  */
     346                 :    2052530 :   if (!TARGET_SUPPORTS_ALIASES)
     347                 :            :     return false;
     348                 :            : 
     349                 :            :   /* Weakrefs have a reason to be non-local.  Be sure we do not replace
     350                 :            :      them.  */
     351                 :    2052540 :   while (node->transparent_alias && node->definition && !node->weakref)
     352                 :         10 :     node = node->get_alias_target ();
     353                 :    2052530 :   if (node->weakref)
     354                 :            :     return false;
     355                 :            :   
     356                 :    2052480 :   return (node->get_availability () > AVAIL_INTERPOSABLE
     357                 :    2000770 :           && !decl_binds_to_current_def_p (node->decl)
     358                 :    3352450 :           && !node->can_be_discarded_p ());
     359                 :            : }
     360                 :            : 
     361                 :            : /* Return true if we can replace reference to NODE by local alias
     362                 :            :    within a virtual table.  Generally we can replace function pointers
     363                 :            :    and virtual table pointers.  */
     364                 :            : 
     365                 :            : static bool
     366                 :     249531 : can_replace_by_local_alias_in_vtable (symtab_node *node)
     367                 :            : {
     368                 :     249531 :   if (is_a <varpool_node *> (node)
     369                 :     145836 :       && !DECL_VIRTUAL_P (node->decl))
     370                 :            :     return false;
     371                 :     165305 :   return can_replace_by_local_alias (node);
     372                 :            : }
     373                 :            : 
     374                 :            : /* walk_tree callback that rewrites initializer references.   */
     375                 :            : 
     376                 :            : static tree
     377                 :         16 : update_vtable_references (tree *tp, int *walk_subtrees,
     378                 :            :                           void *data ATTRIBUTE_UNUSED)
     379                 :            : {
     380                 :         16 :   if (VAR_OR_FUNCTION_DECL_P (*tp))
     381                 :            :     {
     382                 :          2 :       if (can_replace_by_local_alias_in_vtable (symtab_node::get (*tp)))
     383                 :          2 :         *tp = symtab_node::get (*tp)->noninterposable_alias ()->decl;
     384                 :          2 :       *walk_subtrees = 0;
     385                 :            :     }
     386                 :         14 :   else if (IS_TYPE_OR_DECL_P (*tp))
     387                 :          0 :     *walk_subtrees = 0;
     388                 :         16 :   return NULL;
     389                 :            : }
     390                 :            : 
     391                 :            : /* In LTO we can remove COMDAT groups and weak symbols.
     392                 :            :    Either turn them into normal symbols or external symbol depending on 
     393                 :            :    resolution info.  */
     394                 :            : 
     395                 :            : static void
     396                 :   10824100 : update_visibility_by_resolution_info (symtab_node * node)
     397                 :            : {
     398                 :   10824100 :   bool define;
     399                 :            : 
     400                 :   10824100 :   if (!node->externally_visible
     401                 :    4987060 :       || (!DECL_WEAK (node->decl) && !DECL_ONE_ONLY (node->decl))
     402                 :   12781200 :       || node->resolution == LDPR_UNKNOWN)
     403                 :   10823700 :     return;
     404                 :            : 
     405                 :        740 :   define = (node->resolution == LDPR_PREVAILING_DEF_IRONLY
     406                 :            :             || node->resolution == LDPR_PREVAILING_DEF
     407                 :        370 :             || node->resolution == LDPR_UNDEF
     408                 :        370 :             || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
     409                 :            : 
     410                 :            :   /* The linker decisions ought to agree in the whole group.  */
     411                 :        370 :   if (node->same_comdat_group)
     412                 :         99 :     for (symtab_node *next = node->same_comdat_group;
     413                 :        158 :          next != node; next = next->same_comdat_group)
     414                 :            :       {
     415                 :         99 :         if (!next->externally_visible || next->transparent_alias)
     416                 :          4 :           continue;
     417                 :            : 
     418                 :         95 :         bool same_def
     419                 :         95 :           = define == (next->resolution == LDPR_PREVAILING_DEF_IRONLY
     420                 :            :                        || next->resolution == LDPR_PREVAILING_DEF
     421                 :            :                        || next->resolution == LDPR_UNDEF
     422                 :         95 :                        || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
     423                 :         95 :         gcc_assert (in_lto_p || same_def);
     424                 :         95 :         if (!same_def)
     425                 :            :           return;
     426                 :            :       }
     427                 :            : 
     428                 :        370 :   if (node->same_comdat_group)
     429                 :         99 :     for (symtab_node *next = node->same_comdat_group;
     430                 :        158 :          next != node; next = next->same_comdat_group)
     431                 :            :       {
     432                 :            :         /* During incremental linking we need to keep symbol weak for future
     433                 :            :            linking.  We can still drop definition if we know non-LTO world
     434                 :            :            prevails.  */
     435                 :         99 :         if (!flag_incremental_link)
     436                 :            :           {
     437                 :          1 :             DECL_WEAK (next->decl) = false;
     438                 :          1 :             next->set_comdat_group (NULL);
     439                 :            :           }
     440                 :         99 :         if (!define)
     441                 :            :           {
     442                 :          0 :             if (next->externally_visible)
     443                 :          0 :               DECL_EXTERNAL (next->decl) = true;
     444                 :         99 :             next->set_comdat_group (NULL);
     445                 :            :           }
     446                 :            :       }
     447                 :            : 
     448                 :            :   /* During incremental linking we need to keep symbol weak for future
     449                 :            :      linking.  We can still drop definition if we know non-LTO world prevails.  */
     450                 :        370 :   if (!flag_incremental_link)
     451                 :            :     {
     452                 :        222 :       DECL_WEAK (node->decl) = false;
     453                 :        222 :       node->set_comdat_group (NULL);
     454                 :        222 :       node->dissolve_same_comdat_group_list ();
     455                 :            :     }
     456                 :        370 :   if (!define)
     457                 :            :     {
     458                 :          0 :       DECL_EXTERNAL (node->decl) = true;
     459                 :          0 :       node->set_comdat_group (NULL);
     460                 :          0 :       node->dissolve_same_comdat_group_list ();
     461                 :            :     }
     462                 :            : }
     463                 :            : 
     464                 :            : /* Try to get rid of weakref.  */
     465                 :            : 
     466                 :            : static void
     467                 :       3931 : optimize_weakref (symtab_node *node)
     468                 :            : {
     469                 :       3931 :   bool strip_weakref = false;
     470                 :       3931 :   bool static_alias = false;
     471                 :            : 
     472                 :       3931 :   gcc_assert (node->weakref);
     473                 :            : 
     474                 :            :   /* Weakrefs with no target defined cannot be optimized.  */
     475                 :       3931 :   if (!node->analyzed)
     476                 :            :     return;
     477                 :         96 :   symtab_node *target = node->get_alias_target ();
     478                 :            : 
     479                 :            :   /* Weakrefs to weakrefs can be optimized only if target can be.  */
     480                 :         96 :   if (target->weakref)
     481                 :         16 :     optimize_weakref (target);
     482                 :         96 :   if (target->weakref)
     483                 :            :     return;
     484                 :            : 
     485                 :            :   /* If we have definition of weakref's target and we know it binds locally,
     486                 :            :      we can turn weakref to static alias.  */
     487                 :         80 :   if (TARGET_SUPPORTS_ALIASES
     488                 :         80 :       && target->definition && decl_binds_to_current_def_p (target->decl))
     489                 :            :     strip_weakref = static_alias = true;
     490                 :            :   /* Otherwise we can turn weakref into transparent alias.  This transformation
     491                 :            :      may break asm statements which directly refers to symbol name and expect
     492                 :            :      GNU as to translate it via .weakref directive. So do not optimize when
     493                 :            :      DECL_PRESERVED is set and .weakref is supported.  */
     494                 :         47 :   else if ((!DECL_PRESERVE_P (target->decl)
     495                 :          0 :             || IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)))
     496                 :         47 :            && !DECL_WEAK (target->decl)
     497                 :         41 :            && !DECL_EXTERNAL (target->decl)
     498                 :         47 :            && ((target->definition && !target->can_be_discarded_p ())
     499                 :          0 :                || target->resolution != LDPR_UNDEF))
     500                 :            :     strip_weakref = true;
     501                 :         80 :   if (!strip_weakref)
     502                 :            :     return;
     503                 :         33 :   node->weakref = false;
     504                 :         33 :   IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)) = 0;
     505                 :         33 :   TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl)) = NULL_TREE;
     506                 :         99 :   DECL_ATTRIBUTES (node->decl) = remove_attribute ("weakref",
     507                 :         33 :                                                    DECL_ATTRIBUTES
     508                 :            :                                                          (node->decl));
     509                 :            : 
     510                 :         33 :   if (dump_file)
     511                 :          0 :     fprintf (dump_file, "Optimizing weakref %s %s\n",
     512                 :            :              node->dump_name (),
     513                 :            :              static_alias ? "as static alias" : "as transparent alias");
     514                 :            : 
     515                 :         33 :   if (static_alias)
     516                 :            :     {
     517                 :            :       /* make_decl_local will shortcircuit if it doesn't see TREE_PUBLIC.
     518                 :            :          be sure it really clears the WEAK flag.  */
     519                 :         33 :       TREE_PUBLIC (node->decl) = true;
     520                 :         33 :       node->make_decl_local ();
     521                 :         33 :       node->forced_by_abi = false;
     522                 :         33 :       node->resolution = LDPR_PREVAILING_DEF_IRONLY;
     523                 :         33 :       node->externally_visible = false;
     524                 :         33 :       gcc_assert (!DECL_WEAK (node->decl));
     525                 :         33 :       node->transparent_alias = false;
     526                 :            :     }
     527                 :            :   else
     528                 :            :     {
     529                 :          0 :       symtab->change_decl_assembler_name
     530                 :          0 :         (node->decl, DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl));
     531                 :          0 :       node->transparent_alias = true;
     532                 :          0 :       node->copy_visibility_from (target);
     533                 :            :     }
     534                 :         33 :   gcc_assert (node->alias);
     535                 :            : }
     536                 :            : 
     537                 :            : /* NODE is an externally visible definition, which we've discovered is
     538                 :            :    not needed externally.  Make it local to this compilation.  */
     539                 :            : 
     540                 :            : static void
     541                 :    2839690 : localize_node (bool whole_program, symtab_node *node)
     542                 :            : {
     543                 :    2839690 :   gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
     544                 :            : 
     545                 :            :   /* It is possible that one comdat group contains both hidden and non-hidden
     546                 :            :      symbols.  In this case we can privatize all hidden symbol but we need
     547                 :            :      to keep non-hidden exported.  */
     548                 :    2839690 :   if (node->same_comdat_group
     549                 :       8623 :       && (node->resolution == LDPR_PREVAILING_DEF_IRONLY
     550                 :       7014 :           || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP))
     551                 :            :     {
     552                 :            :       symtab_node *next;
     553                 :       1853 :       for (next = node->same_comdat_group;
     554                 :       3517 :            next != node; next = next->same_comdat_group)
     555                 :       1881 :         if (next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
     556                 :       1853 :             || next->resolution == LDPR_PREVAILING_DEF)
     557                 :            :           break;
     558                 :       1664 :       if (node != next)
     559                 :            :         {
     560                 :         28 :           if (!node->transparent_alias)
     561                 :            :             {
     562                 :         28 :               node->resolution = LDPR_PREVAILING_DEF_IRONLY;
     563                 :         28 :               node->make_decl_local ();
     564                 :         28 :               if (!flag_incremental_link)
     565                 :         28 :                 node->unique_name |= true;
     566                 :         28 :               return;
     567                 :            :             }
     568                 :            :         }
     569                 :            :     }
     570                 :            :   /* For similar reason do not privatize whole comdat when seeing comdat
     571                 :            :      local.  Wait for non-comdat symbol to be privatized first.  */
     572                 :    2839660 :   if (node->comdat_local_p ())
     573                 :            :     return;
     574                 :            : 
     575                 :    2832870 :   if (node->same_comdat_group && TREE_PUBLIC (node->decl))
     576                 :            :     {
     577                 :       2161 :       for (symtab_node *next = node->same_comdat_group;
     578                 :       3968 :            next != node; next = next->same_comdat_group)
     579                 :            :         {
     580                 :       2161 :           next->set_comdat_group (NULL);
     581                 :       2161 :           if (!next->alias)
     582                 :       1991 :             next->set_section (NULL);
     583                 :       2161 :           if (!next->transparent_alias)
     584                 :       2161 :             next->make_decl_local ();
     585                 :       2161 :           next->unique_name
     586                 :       2161 :             |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
     587                 :       2161 :                  || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
     588                 :       1789 :                 && TREE_PUBLIC (next->decl)
     589                 :       2161 :                 && !flag_incremental_link);
     590                 :            :         }
     591                 :            : 
     592                 :            :       /* Now everything's localized, the grouping has no meaning, and
     593                 :            :          will cause crashes if we keep it around.  */
     594                 :       1807 :       node->dissolve_same_comdat_group_list ();
     595                 :            :     }
     596                 :            : 
     597                 :    2832870 :   node->unique_name
     598                 :    5665750 :     |= ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
     599                 :    2832870 :          || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
     600                 :    1405400 :         && TREE_PUBLIC (node->decl)
     601                 :    2872430 :         && !flag_incremental_link);
     602                 :            : 
     603                 :    2832870 :   if (TREE_PUBLIC (node->decl))
     604                 :      40423 :     node->set_comdat_group (NULL);
     605                 :    2832870 :   if (DECL_COMDAT (node->decl) && !node->alias)
     606                 :       5433 :     node->set_section (NULL);
     607                 :    2832870 :   if (!node->transparent_alias)
     608                 :            :     {
     609                 :    2832870 :       node->resolution = LDPR_PREVAILING_DEF_IRONLY;
     610                 :    2832870 :       node->make_decl_local ();
     611                 :            :     }
     612                 :            : }
     613                 :            : 
     614                 :            : /* Decide on visibility of all symbols.  */
     615                 :            : 
     616                 :            : static unsigned int
     617                 :     327142 : function_and_variable_visibility (bool whole_program)
     618                 :            : {
     619                 :     327142 :   struct cgraph_node *node;
     620                 :     327142 :   varpool_node *vnode;
     621                 :            : 
     622                 :            :   /* All aliases should be processed at this point.  */
     623                 :     327142 :   gcc_checking_assert (!alias_pairs || !alias_pairs->length ());
     624                 :            : 
     625                 :            : #ifdef ASM_OUTPUT_DEF
     626                 :    7251740 :   FOR_EACH_DEFINED_FUNCTION (node)
     627                 :            :     {
     628                 :    3298730 :       if (node->get_availability () != AVAIL_INTERPOSABLE
     629                 :      67891 :           || DECL_EXTERNAL (node->decl)
     630                 :      71722 :           || node->has_aliases_p ()
     631                 :    3362790 :           || lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)))
     632                 :    3244440 :         continue;
     633                 :            : 
     634                 :      54291 :       cgraph_node *alias = 0;
     635                 :      54291 :       cgraph_edge *next_edge;
     636                 :     261510 :       for (cgraph_edge *e = node->callees; e; e = next_edge)
     637                 :            :         {
     638                 :     207219 :           next_edge = e->next_callee;
     639                 :            :           /* Recursive function calls usually can't be interposed.  */
     640                 :            : 
     641                 :     207219 :           if (!e->recursive_p ())
     642                 :     206447 :             continue;
     643                 :            : 
     644                 :        772 :           if (!alias)
     645                 :            :             {
     646                 :        253 :               alias = dyn_cast<cgraph_node *> (node->noninterposable_alias ());
     647                 :        253 :               gcc_assert (alias && alias != node);
     648                 :            :             }
     649                 :            : 
     650                 :        772 :           e->redirect_callee (alias);
     651                 :        772 :           if (gimple_has_body_p (e->caller->decl))
     652                 :            :             {
     653                 :        772 :               push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
     654                 :        772 :               cgraph_edge::redirect_call_stmt_to_callee (e);
     655                 :        772 :               pop_cfun ();
     656                 :            :             }
     657                 :            :         }
     658                 :            :     }
     659                 :            : #endif
     660                 :            : 
     661                 :   12881100 :   FOR_EACH_FUNCTION (node)
     662                 :            :     {
     663                 :    6113410 :       int flags = flags_from_decl_or_type (node->decl);
     664                 :            : 
     665                 :            :       /* Optimize away PURE and CONST constructors and destructors.  */
     666                 :    6113410 :       if (node->analyzed
     667                 :    3298980 :           && (DECL_STATIC_CONSTRUCTOR (node->decl)
     668                 :    3298980 :               || DECL_STATIC_DESTRUCTOR (node->decl))
     669                 :      20682 :           && (flags & (ECF_CONST | ECF_PURE))
     670                 :         11 :           && !(flags & ECF_LOOPING_CONST_OR_PURE)
     671                 :    6113410 :           && opt_for_fn (node->decl, optimize))
     672                 :            :         {
     673                 :          0 :           DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
     674                 :          0 :           DECL_STATIC_DESTRUCTOR (node->decl) = 0;
     675                 :            :         }
     676                 :            : 
     677                 :            :       /* Frontends and alias code marks nodes as needed before parsing
     678                 :            :          is finished.  We may end up marking as node external nodes
     679                 :            :          where this flag is meaningless strip it.  */
     680                 :    6113410 :       if (DECL_EXTERNAL (node->decl) || !node->definition)
     681                 :            :         {
     682                 :    2997270 :           node->force_output = 0;
     683                 :    2997270 :           node->forced_by_abi = 0;
     684                 :            :         }
     685                 :            : 
     686                 :            :       /* C++ FE on lack of COMDAT support create local COMDAT functions
     687                 :            :          (that ought to be shared but cannot due to object format
     688                 :            :          limitations).  It is necessary to keep the flag to make rest of C++ FE
     689                 :            :          happy.  Clear the flag here to avoid confusion in middle-end.  */
     690                 :    6113410 :       if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
     691                 :         17 :         DECL_COMDAT (node->decl) = 0;
     692                 :            : 
     693                 :            :       /* For external decls stop tracking same_comdat_group. It doesn't matter
     694                 :            :          what comdat group they are in when they won't be emitted in this TU.
     695                 :            : 
     696                 :            :          An exception is LTO where we may end up with both external
     697                 :            :          and non-external declarations in the same comdat group in
     698                 :            :          the case declarations was not merged.  */
     699                 :    6113410 :       if (node->same_comdat_group && DECL_EXTERNAL (node->decl) && !in_lto_p)
     700                 :            :         {
     701                 :         23 :           if (flag_checking)
     702                 :            :             {
     703                 :         31 :               for (symtab_node *n = node->same_comdat_group;
     704                 :         54 :                    n != node;
     705                 :         31 :                    n = n->same_comdat_group)
     706                 :            :                 /* If at least one of same comdat group functions is external,
     707                 :            :                    all of them have to be, otherwise it is a front-end bug.  */
     708                 :         31 :                 gcc_assert (DECL_EXTERNAL (n->decl));
     709                 :            :             }
     710                 :         23 :           node->dissolve_same_comdat_group_list ();
     711                 :            :         }
     712                 :    6113410 :       gcc_assert ((!DECL_WEAK (node->decl)
     713                 :            :                   && !DECL_COMDAT (node->decl))
     714                 :            :                   || TREE_PUBLIC (node->decl)
     715                 :            :                   || node->weakref
     716                 :            :                   || DECL_EXTERNAL (node->decl));
     717                 :    6113410 :       if (cgraph_externally_visible_p (node, whole_program))
     718                 :            :         {
     719                 :    2609700 :           gcc_assert (!node->inlined_to);
     720                 :    2609700 :           node->externally_visible = true;
     721                 :            :         }
     722                 :            :       else
     723                 :            :         {
     724                 :    3503710 :           node->externally_visible = false;
     725                 :    3503710 :           node->forced_by_abi = false;
     726                 :            :         }
     727                 :    6113410 :       if (!node->externally_visible
     728                 :    6113410 :           && node->definition && !node->weakref
     729                 :    6113410 :           && !DECL_EXTERNAL (node->decl))
     730                 :     506380 :         localize_node (whole_program, node);
     731                 :            : 
     732                 :    6113410 :       if (node->thunk.thunk_p
     733                 :       6466 :           && TREE_PUBLIC (node->decl))
     734                 :            :         {
     735                 :       6328 :           struct cgraph_node *decl_node = node;
     736                 :            : 
     737                 :       6328 :           decl_node = decl_node->callees->callee->function_symbol ();
     738                 :            : 
     739                 :            :           /* Thunks have the same visibility as function they are attached to.
     740                 :            :              Make sure the C++ front end set this up properly.  */
     741                 :       6328 :           if (DECL_ONE_ONLY (decl_node->decl))
     742                 :            :             {
     743                 :       4983 :               gcc_checking_assert (DECL_COMDAT (node->decl)
     744                 :            :                                    == DECL_COMDAT (decl_node->decl));
     745                 :       9966 :               gcc_checking_assert (node->in_same_comdat_group_p (decl_node));
     746                 :       4983 :               gcc_checking_assert (node->same_comdat_group);
     747                 :            :             }
     748                 :       6328 :           node->forced_by_abi = decl_node->forced_by_abi;
     749                 :       6328 :           if (DECL_EXTERNAL (decl_node->decl))
     750                 :          4 :             DECL_EXTERNAL (node->decl) = 1;
     751                 :            :         }
     752                 :            : 
     753                 :    6113410 :       update_visibility_by_resolution_info (node);
     754                 :    6113410 :       if (node->weakref)
     755                 :       3857 :         optimize_weakref (node);
     756                 :            :     }
     757                 :    7252250 :   FOR_EACH_DEFINED_FUNCTION (node)
     758                 :            :     {
     759                 :    3298980 :       if (!node->local)
     760                 :    3203480 :         node->local |= node->local_p ();
     761                 :            : 
     762                 :            :       /* If we know that function cannot be overwritten by a
     763                 :            :          different semantics and moreover its section cannot be
     764                 :            :          discarded, replace all direct calls by calls to an
     765                 :            :          noninterposable alias.  This make dynamic linking cheaper and
     766                 :            :          enable more optimization.
     767                 :            : 
     768                 :            :          TODO: We can also update virtual tables.  */
     769                 :    3298980 :       if (node->callers 
     770                 :    3298980 :           && can_replace_by_local_alias (node))
     771                 :            :         {
     772                 :        112 :           cgraph_node *alias = dyn_cast<cgraph_node *>
     773                 :        112 :             (node->noninterposable_alias ());
     774                 :            : 
     775                 :        112 :           if (alias && alias != node)
     776                 :            :             {
     777                 :        256 :               while (node->callers)
     778                 :            :                 {
     779                 :        144 :                   struct cgraph_edge *e = node->callers;
     780                 :            : 
     781                 :        144 :                   e->redirect_callee (alias);
     782                 :        144 :                   if (gimple_has_body_p (e->caller->decl))
     783                 :            :                     {
     784                 :        142 :                       push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
     785                 :        142 :                       cgraph_edge::redirect_call_stmt_to_callee (e);
     786                 :        142 :                       pop_cfun ();
     787                 :            :                     }
     788                 :            :                 }
     789                 :            :             }
     790                 :            :         }
     791                 :            :     }
     792                 :   11031000 :   FOR_EACH_VARIABLE (vnode)
     793                 :            :     {
     794                 :            :       /* weak flag makes no sense on local variables.  */
     795                 :    5188380 :       gcc_assert (!DECL_WEAK (vnode->decl)
     796                 :            :                   || vnode->weakref
     797                 :            :                   || TREE_PUBLIC (vnode->decl)
     798                 :            :                   || DECL_EXTERNAL (vnode->decl));
     799                 :            :       /* In several cases declarations cannot be common:
     800                 :            : 
     801                 :            :          - when declaration has initializer
     802                 :            :          - when it is in weak
     803                 :            :          - when it has specific section
     804                 :            :          - when it resides in non-generic address space.
     805                 :            :          - if declaration is local, it will get into .local common section
     806                 :            :            so common flag is not needed.  Frontends still produce these in
     807                 :            :            certain cases, such as for:
     808                 :            : 
     809                 :            :              static int a __attribute__ ((common))
     810                 :            : 
     811                 :            :          Canonicalize things here and clear the redundant flag.  */
     812                 :    5188380 :       if (DECL_COMMON (vnode->decl)
     813                 :    5211210 :           && (!(TREE_PUBLIC (vnode->decl)
     814                 :      22814 :               || DECL_EXTERNAL (vnode->decl))
     815                 :      22797 :               || (DECL_INITIAL (vnode->decl)
     816                 :      20251 :                   && DECL_INITIAL (vnode->decl) != error_mark_node)
     817                 :       2546 :               || DECL_WEAK (vnode->decl)
     818                 :       2543 :               || DECL_SECTION_NAME (vnode->decl) != NULL
     819                 :       2543 :               || ! (ADDR_SPACE_GENERIC_P
     820                 :    5188380 :                     (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
     821                 :      20271 :         DECL_COMMON (vnode->decl) = 0;
     822                 :    5188380 :       if (vnode->weakref)
     823                 :         58 :         optimize_weakref (vnode);
     824                 :            :     }
     825                 :   10075600 :   FOR_EACH_DEFINED_VARIABLE (vnode)
     826                 :            :     {
     827                 :    4710680 :       if (!vnode->definition)
     828                 :          0 :         continue;
     829                 :    4710680 :       if (vnode->externally_visible_p ())
     830                 :    2377360 :         vnode->externally_visible = true;
     831                 :            :       else
     832                 :            :         {
     833                 :    2333320 :           vnode->externally_visible = false;
     834                 :    2333320 :           vnode->forced_by_abi = false;
     835                 :            :         }
     836                 :    4710680 :       if (lookup_attribute ("no_reorder",
     837                 :    4710680 :                             DECL_ATTRIBUTES (vnode->decl)))
     838                 :          4 :         vnode->no_reorder = 1;
     839                 :            : 
     840                 :    4710680 :       if (!vnode->externally_visible
     841                 :    4710680 :           && !vnode->transparent_alias
     842                 :    4710680 :           && !DECL_EXTERNAL (vnode->decl))
     843                 :    2333310 :         localize_node (whole_program, vnode);
     844                 :            : 
     845                 :    4710680 :       update_visibility_by_resolution_info (vnode);
     846                 :            : 
     847                 :            :       /* Update virtual tables to point to local aliases where possible.  */
     848                 :    4710680 :       if (DECL_VIRTUAL_P (vnode->decl)
     849                 :    4710680 :           && !DECL_EXTERNAL (vnode->decl))
     850                 :            :         {
     851                 :            :           int i;
     852                 :            :           struct ipa_ref *ref;
     853                 :     292073 :           bool found = false;
     854                 :            : 
     855                 :            :           /* See if there is something to update.  */
     856                 :     292073 :           for (i = 0; vnode->iterate_reference (i, ref); i++)
     857                 :     249529 :             if (ref->use == IPA_REF_ADDR
     858                 :     249529 :                 && can_replace_by_local_alias_in_vtable (ref->referred))
     859                 :            :               {
     860                 :            :                 found = true;
     861                 :            :                 break;
     862                 :            :               }
     863                 :      42546 :           if (found)
     864                 :            :             {
     865                 :          4 :               hash_set<tree> visited_nodes;
     866                 :            : 
     867                 :          2 :               vnode->get_constructor ();
     868                 :          2 :               walk_tree (&DECL_INITIAL (vnode->decl),
     869                 :            :                          update_vtable_references, NULL, &visited_nodes);
     870                 :          2 :               vnode->remove_all_references ();
     871                 :          2 :               record_references_in_initializer (vnode->decl, false);
     872                 :            :             }
     873                 :            :         }
     874                 :            :     }
     875                 :            : 
     876                 :     327142 :   if (dump_file)
     877                 :            :     {
     878                 :        116 :       fprintf (dump_file, "\nMarking local functions:");
     879                 :        556 :       FOR_EACH_DEFINED_FUNCTION (node)
     880                 :        162 :         if (node->local)
     881                 :          0 :           fprintf (dump_file, " %s", node->dump_name ());
     882                 :        116 :       fprintf (dump_file, "\n\n");
     883                 :        116 :       fprintf (dump_file, "\nMarking externally visible functions:");
     884                 :        556 :       FOR_EACH_DEFINED_FUNCTION (node)
     885                 :        162 :         if (node->externally_visible)
     886                 :        158 :           fprintf (dump_file, " %s", node->dump_name ());
     887                 :        116 :       fprintf (dump_file, "\n\n");
     888                 :        116 :       fprintf (dump_file, "\nMarking externally visible variables:");
     889                 :        376 :       FOR_EACH_DEFINED_VARIABLE (vnode)
     890                 :         72 :         if (vnode->externally_visible)
     891                 :         34 :           fprintf (dump_file, " %s", vnode->dump_name ());
     892                 :        116 :       fprintf (dump_file, "\n\n");
     893                 :            :     }
     894                 :     327142 :   symtab->function_flags_ready = true;
     895                 :     327142 :   return 0;
     896                 :            : }
     897                 :            : 
     898                 :            : /* Local function pass handling visibilities.  This happens before LTO streaming
     899                 :            :    so in particular -fwhole-program should be ignored at this level.  */
     900                 :            : 
     901                 :            : namespace {
     902                 :            : 
     903                 :            : const pass_data pass_data_ipa_function_and_variable_visibility =
     904                 :            : {
     905                 :            :   SIMPLE_IPA_PASS, /* type */
     906                 :            :   "visibility", /* name */
     907                 :            :   OPTGROUP_NONE, /* optinfo_flags */
     908                 :            :   TV_CGRAPHOPT, /* tv_id */
     909                 :            :   0, /* properties_required */
     910                 :            :   0, /* properties_provided */
     911                 :            :   0, /* properties_destroyed */
     912                 :            :   0, /* todo_flags_start */
     913                 :            :   ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
     914                 :            : };
     915                 :            : 
     916                 :            : /* Bring functions local at LTO time with -fwhole-program.  */
     917                 :            : 
     918                 :            : static unsigned int
     919                 :     163705 : whole_program_function_and_variable_visibility (void)
     920                 :            : {
     921                 :     163705 :   function_and_variable_visibility (flag_whole_program);
     922                 :     163705 :   if (optimize || in_lto_p)
     923                 :     110920 :     ipa_discover_variable_flags ();
     924                 :     163705 :   return 0;
     925                 :            : }
     926                 :            : 
     927                 :            : } // anon namespace
     928                 :            : 
     929                 :            : namespace {
     930                 :            : 
     931                 :            : const pass_data pass_data_ipa_whole_program_visibility =
     932                 :            : {
     933                 :            :   IPA_PASS, /* type */
     934                 :            :   "whole-program", /* name */
     935                 :            :   OPTGROUP_NONE, /* optinfo_flags */
     936                 :            :   TV_CGRAPHOPT, /* tv_id */
     937                 :            :   0, /* properties_required */
     938                 :            :   0, /* properties_provided */
     939                 :            :   0, /* properties_destroyed */
     940                 :            :   0, /* todo_flags_start */
     941                 :            :   ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
     942                 :            : };
     943                 :            : 
     944                 :            : class pass_ipa_whole_program_visibility : public ipa_opt_pass_d
     945                 :            : {
     946                 :            : public:
     947                 :     200773 :   pass_ipa_whole_program_visibility (gcc::context *ctxt)
     948                 :            :     : ipa_opt_pass_d (pass_data_ipa_whole_program_visibility, ctxt,
     949                 :            :                       NULL, /* generate_summary */
     950                 :            :                       NULL, /* write_summary */
     951                 :            :                       NULL, /* read_summary */
     952                 :            :                       NULL, /* write_optimization_summary */
     953                 :            :                       NULL, /* read_optimization_summary */
     954                 :            :                       NULL, /* stmt_fixup */
     955                 :            :                       0, /* function_transform_todo_flags_start */
     956                 :            :                       NULL, /* function_transform */
     957                 :     401546 :                       NULL) /* variable_transform */
     958                 :            :   {}
     959                 :            : 
     960                 :            :   /* opt_pass methods: */
     961                 :            : 
     962                 :     415684 :   virtual bool gate (function *)
     963                 :            :     {
     964                 :            :       /* Do not re-run on ltrans stage.  */
     965                 :     415684 :       return !flag_ltrans;
     966                 :            :     }
     967                 :     163705 :   virtual unsigned int execute (function *)
     968                 :            :     {
     969                 :     163705 :       return whole_program_function_and_variable_visibility ();
     970                 :            :     }
     971                 :            : 
     972                 :            : }; // class pass_ipa_whole_program_visibility
     973                 :            : 
     974                 :            : } // anon namespace
     975                 :            : 
     976                 :            : ipa_opt_pass_d *
     977                 :     200773 : make_pass_ipa_whole_program_visibility (gcc::context *ctxt)
     978                 :            : {
     979                 :     200773 :   return new pass_ipa_whole_program_visibility (ctxt);
     980                 :            : }
     981                 :            : 
     982                 :            : class pass_ipa_function_and_variable_visibility : public simple_ipa_opt_pass
     983                 :            : {
     984                 :            : public:
     985                 :     200773 :   pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
     986                 :            :     : simple_ipa_opt_pass (pass_data_ipa_function_and_variable_visibility,
     987                 :     401546 :                            ctxt)
     988                 :            :   {}
     989                 :            : 
     990                 :            :   /* opt_pass methods: */
     991                 :     163437 :   virtual unsigned int execute (function *)
     992                 :            :     {
     993                 :     326780 :       return function_and_variable_visibility (flag_whole_program && !flag_lto);
     994                 :            :     }
     995                 :            : 
     996                 :            : }; // class pass_ipa_function_and_variable_visibility
     997                 :            : 
     998                 :            : simple_ipa_opt_pass *
     999                 :     200773 : make_pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
    1000                 :            : {
    1001                 :     200773 :   return new pass_ipa_function_and_variable_visibility (ctxt);
    1002                 :            : }

Generated by: LCOV version 1.0

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto --enable-host-shared. GCC test suite is run with the built compiler.